mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-15 08:18:55 +00:00
Merge pull request #1595 from eclipse/cd_moreTestX2J
[eclipse/xtext#1837] converted xtend 2 java
This commit is contained in:
commit
be53e1d841
60 changed files with 2534 additions and 5644 deletions
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* Copyright (c) 2017, 2020 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.lsp4j.CodeLens;
|
||||
import org.eclipse.lsp4j.Position;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* @author Sven Efftinge - Initial contribution and API
|
||||
*/
|
||||
public class CodeLensTest extends AbstractTestLangLanguageServerTest {
|
||||
@Test
|
||||
public void testCodeLens() {
|
||||
testCodeLens((TestCodeLensConfiguration cfg) -> {
|
||||
String model =
|
||||
"type Foo {}\n" +
|
||||
"type Bar {\n" +
|
||||
" Foo foo\n" +
|
||||
"}";
|
||||
cfg.setModel(model);
|
||||
cfg.setAssertCodeLenses((List<? extends CodeLens> result) -> {
|
||||
CodeLens first = Iterables.getFirst(result, null);
|
||||
assertEquals("Do Awesome Stuff(RESOLVED)", first.getCommand().getTitle());
|
||||
Assert.assertEquals(1, ((Position) first.getData()).getLine());
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.tests.server
|
||||
|
||||
import org.eclipse.lsp4j.Position
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* @author Sven Efftinge - Initial contribution and API
|
||||
*/
|
||||
class CodeLensTest extends AbstractTestLangLanguageServerTest {
|
||||
|
||||
@Test def void testCodeLens() {
|
||||
testCodeLens [
|
||||
model = '''
|
||||
type Foo {}
|
||||
type Bar {
|
||||
Foo foo
|
||||
}
|
||||
'''
|
||||
assertCodeLenses = [
|
||||
assertEquals("Do Awesome Stuff(RESOLVED)", head.command.title)
|
||||
Assert.assertEquals(1, (head.data as Position).line)
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/**
|
||||
* Copyright (c) 2018, 2020 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.eclipse.lsp4j.ClientCapabilities;
|
||||
import org.eclipse.lsp4j.ExecuteCommandCapabilities;
|
||||
import org.eclipse.lsp4j.ExecuteCommandParams;
|
||||
import org.eclipse.lsp4j.InitializeParams;
|
||||
import org.eclipse.lsp4j.WorkspaceClientCapabilities;
|
||||
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Christian Dietrich - Initial contribution and API
|
||||
*/
|
||||
public class CommandServiceTest extends AbstractTestLangLanguageServerTest {
|
||||
public static class TestExecuteCommandConfiguration {
|
||||
private String command = "";
|
||||
|
||||
private List<Object> args = new ArrayList<Object>();
|
||||
|
||||
private Consumer<Object> assertCommandResult = null;
|
||||
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public void setCommand(String command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public List<Object> getArgs() {
|
||||
return args;
|
||||
}
|
||||
|
||||
public void setArgs(List<Object> args) {
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public Consumer<Object> getAssertCommandResult() {
|
||||
return assertCommandResult;
|
||||
}
|
||||
|
||||
public void setAssertCommandResult(Consumer<Object> assertCommandResult) {
|
||||
this.assertCommandResult = assertCommandResult;
|
||||
}
|
||||
}
|
||||
|
||||
protected void testExecuteCommand(Procedure1<? super TestExecuteCommandConfiguration> configurator)
|
||||
throws Exception {
|
||||
TestExecuteCommandConfiguration configuration = new TestExecuteCommandConfiguration();
|
||||
configurator.apply(configuration);
|
||||
String command = configuration.command;
|
||||
List<Object> args = configuration.args;
|
||||
CompletableFuture<Object> result = languageServer.executeCommand(new ExecuteCommandParams(command, args));
|
||||
if (configuration.assertCommandResult != null) {
|
||||
Object value = result.get();
|
||||
configuration.assertCommandResult.accept(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecute() throws Exception {
|
||||
initialize((InitializeParams it) -> {
|
||||
ClientCapabilities clientCapabilities = new ClientCapabilities();
|
||||
WorkspaceClientCapabilities workspaceClientCapabilities = new WorkspaceClientCapabilities();
|
||||
workspaceClientCapabilities.setExecuteCommand(new ExecuteCommandCapabilities(true));
|
||||
clientCapabilities.setWorkspace(workspaceClientCapabilities);
|
||||
it.setCapabilities(clientCapabilities);
|
||||
});
|
||||
testExecuteCommand((TestExecuteCommandConfiguration cfg) -> {
|
||||
cfg.command = "testlang.a";
|
||||
cfg.assertCommandResult = (Object o) -> {
|
||||
if (o instanceof String) {
|
||||
assertEquals("a", (String) o);
|
||||
} else {
|
||||
Assert.fail("no string");
|
||||
}
|
||||
};
|
||||
});
|
||||
testExecuteCommand((TestExecuteCommandConfiguration cfg) -> {
|
||||
cfg.command = "testlang.b";
|
||||
cfg.assertCommandResult = (Object o) -> {
|
||||
if (o instanceof String) {
|
||||
assertEquals("b", (String) o);
|
||||
} else {
|
||||
Assert.fail("no string");
|
||||
}
|
||||
};
|
||||
});
|
||||
testExecuteCommand((TestExecuteCommandConfiguration cfg) -> {
|
||||
cfg.command = "doesnotexist.c";
|
||||
cfg.assertCommandResult = (Object o) -> {
|
||||
Assert.assertNull(o);
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2018 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.tests.server
|
||||
|
||||
import java.util.ArrayList
|
||||
import java.util.List
|
||||
import java.util.function.Consumer
|
||||
import org.eclipse.lsp4j.ClientCapabilities
|
||||
import org.eclipse.lsp4j.ExecuteCommandCapabilities
|
||||
import org.eclipse.lsp4j.ExecuteCommandParams
|
||||
import org.eclipse.lsp4j.WorkspaceClientCapabilities
|
||||
import org.eclipse.xtend.lib.annotations.Accessors
|
||||
import static org.junit.Assert.*
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* @author Christian Dietrich - Initial contribution and API
|
||||
*/
|
||||
class CommandServiceTest extends AbstractTestLangLanguageServerTest {
|
||||
|
||||
@Accessors static class TestExecuteCommandConfiguration {
|
||||
String command = ''
|
||||
List<Object> args = new ArrayList
|
||||
|
||||
Consumer<Object> assertCommandResult= null
|
||||
}
|
||||
|
||||
protected def void testExecuteCommand((TestExecuteCommandConfiguration)=>void configurator) {
|
||||
val extension configuration = new TestExecuteCommandConfiguration
|
||||
configurator.apply(configuration)
|
||||
val command = configuration.command
|
||||
val args = configuration.args
|
||||
val result = languageServer.executeCommand(new ExecuteCommandParams(command, args))
|
||||
if (configuration.assertCommandResult !== null) {
|
||||
val value = result.get
|
||||
configuration.assertCommandResult.accept(value)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
def void testExecute() {
|
||||
initialize[
|
||||
capabilities = new ClientCapabilities => [
|
||||
workspace = new WorkspaceClientCapabilities => [
|
||||
executeCommand = new ExecuteCommandCapabilities => [
|
||||
dynamicRegistration = true
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
testExecuteCommand [
|
||||
command = "testlang.a"
|
||||
assertCommandResult = [
|
||||
if (it instanceof String) {
|
||||
assertEquals("a", it)
|
||||
} else {
|
||||
fail("no string")
|
||||
}
|
||||
]
|
||||
]
|
||||
testExecuteCommand [
|
||||
command = "testlang.b"
|
||||
assertCommandResult = [
|
||||
if (it instanceof String) {
|
||||
assertEquals("b", it)
|
||||
} else {
|
||||
fail("no string")
|
||||
}
|
||||
]
|
||||
]
|
||||
testExecuteCommand [
|
||||
command = "doesnotexist.c"
|
||||
assertCommandResult = [
|
||||
assertNull(it)
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* Copyright (c) 2016, 2020 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import org.eclipse.xtext.testing.DefinitionTestConfiguration;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author kosyakov - Initial contribution and API
|
||||
*/
|
||||
public class DefinitionTest extends AbstractTestLangLanguageServerTest {
|
||||
@Test
|
||||
public void testDefinition_01() {
|
||||
testDefinition((DefinitionTestConfiguration cfg) -> {
|
||||
String model =
|
||||
"type Foo {}\n" +
|
||||
"type Bar {\n" +
|
||||
" Foo foo\n" +
|
||||
"}";
|
||||
cfg.setModel(model);
|
||||
cfg.setLine(2);
|
||||
cfg.setColumn(3);
|
||||
cfg.setExpectedDefinitions("MyModel.testlang [[0, 5] .. [0, 8]]\n");
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.tests.server
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* @author kosyakov - Initial contribution and API
|
||||
*/
|
||||
class DefinitionTest extends AbstractTestLangLanguageServerTest {
|
||||
|
||||
@Test
|
||||
def void testDefinition_01() {
|
||||
testDefinition[
|
||||
model = '''
|
||||
type Foo {}
|
||||
type Bar {
|
||||
Foo foo
|
||||
}
|
||||
'''
|
||||
line = 2
|
||||
column = 3
|
||||
expectedDefinitions = '''
|
||||
MyModel.testlang [[0, 5] .. [0, 8]]
|
||||
'''
|
||||
]
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
/**
|
||||
* Copyright (c) 2016, 2020 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import org.eclipse.lsp4j.DocumentHighlight;
|
||||
import org.eclipse.lsp4j.DocumentHighlightKind;
|
||||
import org.eclipse.xtext.ide.server.occurrences.IDocumentHighlightService;
|
||||
import org.eclipse.xtext.testing.DocumentHighlightConfiguration;
|
||||
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Class for testing the {@link DocumentHighlightService document highlight
|
||||
* service} behavior through the language server.
|
||||
*
|
||||
* <p>
|
||||
* The string representation of on single {@link DocumentHighlight highlight}
|
||||
* instance is represented with the below pattern:
|
||||
*
|
||||
* <pre>
|
||||
* R|W|T [{d}+, {d}+] .. [{d}+, {d}+]
|
||||
* </pre>
|
||||
*
|
||||
* where the first character describes the {@link DocumentHighlightKind kind} of
|
||||
* the document highlight. If missing, then the value is {@code NaN}. The values
|
||||
* between the first square brackets are the start {@link Position#getLine()
|
||||
* line} and the (zero-based) {@link Position#getCharacter() character offset}
|
||||
* in the line. The second square brackets contains the end position of the
|
||||
* selection and described with the same semantics as the first start range.
|
||||
* Multiple highlight instances are separated by the {@code |} ("pipe")
|
||||
* character.
|
||||
*
|
||||
* @author akos.kitta - Initial contribution and API
|
||||
*
|
||||
* @see DocumentHighlight
|
||||
* @see IDocumentHighlightService
|
||||
*/
|
||||
public class DocumentHighlightTest extends AbstractTestLangLanguageServerTest {
|
||||
@Test
|
||||
public void singleLineNoOccurrences_SelectionBeforeWriteScfgeMethodName() {
|
||||
testDocumentHighlight((DocumentHighlightConfiguration cfg) -> {
|
||||
cfg.setModel("type A { op foo() { } }");
|
||||
cfg.setColumn("type A { op".length());
|
||||
cfg.setExpectedDocumentHighlight("");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleLineNoOccurrences_SelectionAfterWriteSiteMethodName() {
|
||||
testDocumentHighlight((DocumentHighlightConfiguration cfg) -> {
|
||||
cfg.setModel("type A { op foo() { } }");
|
||||
cfg.setColumn("type A { op foo(".length());
|
||||
cfg.setExpectedDocumentHighlight("");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleLineSingleOccurrence() {
|
||||
testDocumentHighlight((DocumentHighlightConfiguration cfg) -> {
|
||||
cfg.setModel("type A { op foo() { } }");
|
||||
cfg.setColumn("type A { op fo".length());
|
||||
cfg.setExpectedDocumentHighlight("W [[0, 12] .. [0, 15]]");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleLineSingleOccurrenceWithVariable() {
|
||||
testDocumentHighlight((DocumentHighlightConfiguration cfg) -> {
|
||||
cfg.setModel("type A { int foo op foo() { } }");
|
||||
cfg.setColumn("type A { int fo".length());
|
||||
cfg.setExpectedDocumentHighlight("W [[0, 13] .. [0, 16]]");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleLineSingleOccurrenceWithMultipleTypes() {
|
||||
testDocumentHighlight((DocumentHighlightConfiguration cfg) -> {
|
||||
cfg.setModel("type A { op foo() { } } type B { op foo() { } }");
|
||||
cfg.setColumn("type A { op fo".length());
|
||||
cfg.setExpectedDocumentHighlight("W [[0, 12] .. [0, 15]]");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleLineMultipleOccurrences_SelectionOnReadSite() {
|
||||
testDocumentHighlight((DocumentHighlightConfiguration cfg) -> {
|
||||
cfg.setModel("type A { op foo() { } op bar() { foo(10) } }");
|
||||
cfg.setLine(0);
|
||||
cfg.setColumn("type A { op foo() { } op bar() { fo".length());
|
||||
cfg.setExpectedDocumentHighlight("W [[0, 12] .. [0, 15]] | R [[0, 33] .. [0, 36]]");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleLineMultipleOccurrences_SelectionOnWriteSite() {
|
||||
testDocumentHighlight((DocumentHighlightConfiguration cfg) -> {
|
||||
cfg.setModel("type A { op foo() { } op bar() { foo(10) } }");
|
||||
cfg.setLine(0);
|
||||
cfg.setColumn("type A { op fo".length());
|
||||
cfg.setExpectedDocumentHighlight("W [[0, 12] .. [0, 15]] | R [[0, 33] .. [0, 36]]");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleLinesMultipleOccurrences_WithHorizontalTabs() {
|
||||
testDocumentHighlight((Procedure1<DocumentHighlightConfiguration>) (DocumentHighlightConfiguration cfg) -> {
|
||||
String model =
|
||||
"type A {\n" +
|
||||
" op foo() { }\n" +
|
||||
" op bar() {\n" +
|
||||
" foo(10)\n" +
|
||||
" }\n}";
|
||||
cfg.setModel(model);
|
||||
cfg.setLine(1);
|
||||
cfg.setColumn("\top fo".length());
|
||||
cfg.setExpectedDocumentHighlight("W [[1, 4] .. [1, 7]] | R [[3, 2] .. [3, 5]]");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleLinesMultipleOccurrences_WithWhitespaces() {
|
||||
testDocumentHighlight((DocumentHighlightConfiguration cfg) -> {
|
||||
String model =
|
||||
"type A {\n" +
|
||||
" op foo() { }\n" +
|
||||
" op bar() {\n" +
|
||||
" foo(10)\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
cfg.setModel(model);
|
||||
cfg.setLine(1);
|
||||
cfg.setColumn(" op fo".length());
|
||||
cfg.setExpectedDocumentHighlight("W [[1, 7] .. [1, 10]] | R [[3, 8] .. [3, 11]]");
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,146 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.tests.server
|
||||
|
||||
import org.eclipse.lsp4j.DocumentHighlight
|
||||
import org.eclipse.lsp4j.DocumentHighlightKind
|
||||
import org.eclipse.lsp4j.Position
|
||||
import org.eclipse.xtext.ide.server.occurrences.IDocumentHighlightService
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* Class for testing the {@link DocumentHighlightService document highlight
|
||||
* service} behavior through the language server.
|
||||
*
|
||||
* <p>
|
||||
* The string representation of on single {@link DocumentHighlight highlight}
|
||||
* instance is represented with the below pattern:
|
||||
*
|
||||
* <pre>
|
||||
* R|W|T [{d}+, {d}+] .. [{d}+, {d}+]
|
||||
* </pre>
|
||||
*
|
||||
* where the first character describes the {@link DocumentHighlightKind kind} of
|
||||
* the document highlight. If missing, then the value is {@code NaN}. The values
|
||||
* between the first square brackets are the start {@link Position#getLine()
|
||||
* line} and the (zero-based) {@link Position#getCharacter() character offset}
|
||||
* in the line. The second square brackets contains the end position of the
|
||||
* selection and described with the same semantics as the first start range.
|
||||
* Multiple highlight instances are separated by the {@code |} ("pipe")
|
||||
* character.
|
||||
*
|
||||
* @author akos.kitta - Initial contribution and API
|
||||
*
|
||||
* @see DocumentHighlight
|
||||
* @see IDocumentHighlightService
|
||||
*/
|
||||
class DocumentHighlightTest extends AbstractTestLangLanguageServerTest {
|
||||
|
||||
@Test
|
||||
def void singleLineNoOccurrences_SelectionBeforeWriteSiteMethodName() {
|
||||
testDocumentHighlight[
|
||||
model = '''type A { op foo() { } }''';
|
||||
column = '''type A { op'''.length;
|
||||
expectedDocumentHighlight = '';
|
||||
];
|
||||
}
|
||||
|
||||
@Test
|
||||
def void singleLineNoOccurrences_SelectionAfterWriteSiteMethodName() {
|
||||
testDocumentHighlight[
|
||||
model = '''type A { op foo() { } }''';
|
||||
column = '''type A { op foo('''.length;
|
||||
expectedDocumentHighlight = '';
|
||||
];
|
||||
}
|
||||
|
||||
@Test
|
||||
def void singleLineSingleOccurrence() {
|
||||
testDocumentHighlight[
|
||||
model = '''type A { op foo() { } }''';
|
||||
column = '''type A { op fo'''.length;
|
||||
expectedDocumentHighlight = 'W [[0, 12] .. [0, 15]]';
|
||||
];
|
||||
}
|
||||
|
||||
@Test
|
||||
def void singleLineSingleOccurrenceWithVariable() {
|
||||
testDocumentHighlight[
|
||||
model = '''type A { int foo op foo() { } }''';
|
||||
column = '''type A { int fo'''.length;
|
||||
expectedDocumentHighlight = 'W [[0, 13] .. [0, 16]]';
|
||||
];
|
||||
}
|
||||
|
||||
@Test
|
||||
def void singleLineSingleOccurrenceWithMultipleTypes() {
|
||||
testDocumentHighlight[
|
||||
model = '''type A { op foo() { } } type B { op foo() { } }''';
|
||||
column = '''type A { op fo'''.length;
|
||||
expectedDocumentHighlight = 'W [[0, 12] .. [0, 15]]';
|
||||
];
|
||||
}
|
||||
|
||||
@Test
|
||||
def void singleLineMultipleOccurrences_SelectionOnReadSite() {
|
||||
testDocumentHighlight[
|
||||
model = '''type A { op foo() { } op bar() { foo(10) } }''';
|
||||
line = 0;
|
||||
column = '''type A { op foo() { } op bar() { fo'''.length;
|
||||
expectedDocumentHighlight = 'W [[0, 12] .. [0, 15]] | R [[0, 33] .. [0, 36]]';
|
||||
];
|
||||
}
|
||||
|
||||
@Test
|
||||
def void singleLineMultipleOccurrences_SelectionOnWriteSite() {
|
||||
testDocumentHighlight[
|
||||
model = '''type A { op foo() { } op bar() { foo(10) } }''';
|
||||
line = 0;
|
||||
column = '''type A { op fo'''.length;
|
||||
expectedDocumentHighlight = 'W [[0, 12] .. [0, 15]] | R [[0, 33] .. [0, 36]]';
|
||||
];
|
||||
}
|
||||
|
||||
@Test
|
||||
def void multipleLinesMultipleOccurrences_WithHorizontalTabs() {
|
||||
testDocumentHighlight[
|
||||
// This snippet contains horizontal tabs for code indentation
|
||||
model = '''
|
||||
type A {
|
||||
op foo() { }
|
||||
op bar() {
|
||||
foo(10)
|
||||
}
|
||||
}''';
|
||||
line = 1;
|
||||
// Same as above, horizontal tabs for code indentation
|
||||
column = ''' op fo'''.length;
|
||||
expectedDocumentHighlight = 'W [[1, 4] .. [1, 7]] | R [[3, 2] .. [3, 5]]';
|
||||
];
|
||||
}
|
||||
|
||||
@Test
|
||||
def void multipleLinesMultipleOccurrences_WithWhitespaces() {
|
||||
testDocumentHighlight[
|
||||
// This snippet contains spaces for code indentation
|
||||
model = '''
|
||||
type A {
|
||||
op foo() { }
|
||||
op bar() {
|
||||
foo(10)
|
||||
}
|
||||
}''';
|
||||
line = 1;
|
||||
// Same as above, spaces for code indentation
|
||||
column = ''' op fo'''.length;
|
||||
expectedDocumentHighlight = 'W [[1, 7] .. [1, 10]] | R [[3, 8] .. [3, 11]]';
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Copyright (c) 2019, 2020 Sigasi N.V. (http://www.sigasi.com) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import org.eclipse.xtext.testing.AbstractLanguageServerTest;
|
||||
import org.eclipse.xtext.testing.DocumentHighlightConfiguration;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Class for testing the highlighting of reference that refer to the object in
|
||||
* which they are embedded.
|
||||
*/
|
||||
public class DocumentHighlightTest2 extends AbstractLanguageServerTest {
|
||||
public DocumentHighlightTest2() {
|
||||
super("nestedRefs");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHighlightDeclarationWithNestedReference() {
|
||||
testDocumentHighlight((DocumentHighlightConfiguration cfg) -> {
|
||||
cfg.setModel("decl myDecl end myDecl;");
|
||||
cfg.setLine(0);
|
||||
cfg.setColumn("decl myDec".length());
|
||||
cfg.setExpectedDocumentHighlight("W [[0, 5] .. [0, 11]] | R [[0, 16] .. [0, 22]]");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHighlightNestedReferenceInsideDeclaration() {
|
||||
testDocumentHighlight((DocumentHighlightConfiguration cfg) -> {
|
||||
cfg.setModel("decl myDecl end myDecl;");
|
||||
cfg.setLine(0);
|
||||
cfg.setColumn("decl myDecl end myDe".length());
|
||||
cfg.setExpectedDocumentHighlight("W [[0, 5] .. [0, 11]] | R [[0, 16] .. [0, 22]]");
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2019 Sigasi N.V. (http://www.sigasi.com) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.tests.server
|
||||
|
||||
import org.eclipse.xtext.testing.AbstractLanguageServerTest
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* Class for testing the highlighting of reference that refer to the object in which they are embedded.
|
||||
*/
|
||||
class DocumentHighlightTest2 extends AbstractLanguageServerTest {
|
||||
|
||||
new() {
|
||||
super('nestedRefs');
|
||||
}
|
||||
|
||||
@Test
|
||||
def void testHighlightDeclarationWithNestedReference() {
|
||||
testDocumentHighlight[
|
||||
model = '''
|
||||
decl myDecl end myDecl;
|
||||
''';
|
||||
|
||||
line = 0
|
||||
column = '''decl myDec'''.length;
|
||||
expectedDocumentHighlight = 'W [[0, 5] .. [0, 11]] | R [[0, 16] .. [0, 22]]';
|
||||
];
|
||||
}
|
||||
|
||||
@Test
|
||||
def void testHighlightNestedReferenceInsideDeclaration() {
|
||||
testDocumentHighlight[
|
||||
model = '''
|
||||
decl myDecl end myDecl;
|
||||
''';
|
||||
|
||||
line = 0
|
||||
column = '''decl myDecl end myDe'''.length;
|
||||
expectedDocumentHighlight = 'W [[0, 5] .. [0, 11]] | R [[0, 16] .. [0, 22]]';
|
||||
];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
/**
|
||||
* Copyright (c) 2019, 2020 NumberFour AG (http://www.enfore.com) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.lsp4j.DidChangeWatchedFilesParams;
|
||||
import org.eclipse.lsp4j.FileChangeType;
|
||||
import org.eclipse.lsp4j.FileEvent;
|
||||
import org.eclipse.lsp4j.WorkspaceFolder;
|
||||
import org.eclipse.xtext.ide.server.IMultiRootWorkspaceConfigFactory;
|
||||
import org.eclipse.xtext.ide.server.MultiRootWorkspaceConfigFactory;
|
||||
import org.eclipse.xtext.ide.server.ServerModule;
|
||||
import org.eclipse.xtext.testing.ReferenceTestConfiguration;
|
||||
import org.eclipse.xtext.util.Modules2;
|
||||
import org.eclipse.xtext.workspace.FileProjectConfig;
|
||||
import org.eclipse.xtext.workspace.WorkspaceConfig;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.inject.Binder;
|
||||
import com.google.inject.Module;
|
||||
|
||||
/**
|
||||
* Checks functionality of method IProjectConfig#isIndexOnly()
|
||||
*
|
||||
* @author Marcus Mews - Initial contribution and API
|
||||
*/
|
||||
public class IndexOnlyProjectTest extends AbstractTestLangLanguageServerTest {
|
||||
@Override
|
||||
public com.google.inject.Module getServerModule() {
|
||||
return Modules2.mixin(new ServerModule(), new Module() {
|
||||
|
||||
@Override
|
||||
public void configure(Binder binder) {
|
||||
binder.bind(IMultiRootWorkspaceConfigFactory.class).toInstance(new MultiRootWorkspaceConfigFactory() {
|
||||
@Override
|
||||
public void addProjectsForWorkspaceFolder(WorkspaceConfig workspaceConfig,
|
||||
WorkspaceFolder workspaceFolder, Set<String> existingNames) {
|
||||
String uri = null;
|
||||
if (workspaceFolder != null) {
|
||||
uri = workspaceFolder.getUri();
|
||||
}
|
||||
if (uri != null) {
|
||||
FileProjectConfig project = new FileProjectConfig(
|
||||
getUriExtensions().toUri(workspaceFolder.getUri()),
|
||||
getUniqueProjectName(workspaceFolder.getName(), existingNames)) {
|
||||
@Override
|
||||
public boolean isIndexOnly() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
project.addSourceFolder(".");
|
||||
workspaceConfig.addProject(project);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows that the resource is indexed
|
||||
*/
|
||||
@Test
|
||||
public void testIndexByUsingReferences() {
|
||||
testReferences((ReferenceTestConfiguration cfg) -> {
|
||||
String model = "type Foo {}\n" + "type Bar {\n" + " Foo foo\n" + "}\n";
|
||||
cfg.setModel(model);
|
||||
cfg.setColumn("type F".length());
|
||||
cfg.setExpectedReferences("MyModel.testlang [[2, 1] .. [2, 4]]\n");
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows that the resource is not validated during initial build
|
||||
*/
|
||||
@Test
|
||||
public void testInitializeBuildNoValidation() {
|
||||
writeFile("MyType1.testlang", "type Test { NonExisting foo }");
|
||||
initialize();
|
||||
Assert.assertTrue(Joiner.on(",").join(getDiagnostics().entrySet()), getDiagnostics().isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows that the error-free resource is not generated during initial build
|
||||
*/
|
||||
@Test
|
||||
public void testInitializeBuildNoGeneration() {
|
||||
writeFile("MyType1.testlang", "type TestType { int foo }");
|
||||
initialize();
|
||||
File outputFile = new File(root, "src-gen/TestType.java");
|
||||
Assert.assertFalse(Joiner.on(",").join(getDiagnostics().entrySet()), outputFile.isFile());
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows that the resource is not validated during incremental build
|
||||
*/
|
||||
@Test
|
||||
public void testIncrementalBuildNoValidation() {
|
||||
writeFile("MyType1.testlang", "type Test { NonExisting foo }");
|
||||
initialize();
|
||||
Assert.assertTrue(Joiner.on(",").join(getDiagnostics().entrySet()), getDiagnostics().isEmpty());
|
||||
String path = writeFile("MyType2.testlang", "type NonExisting {}");
|
||||
languageServer.getWorkspaceService().didChangeWatchedFiles(
|
||||
new DidChangeWatchedFilesParams(Lists.newArrayList(new FileEvent(path, FileChangeType.Created))));
|
||||
Assert.assertTrue(Joiner.on(",").join(getDiagnostics().entrySet()), getDiagnostics().isEmpty());
|
||||
}
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2019 NumberFour AG (http://www.enfore.com) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.tests.server
|
||||
|
||||
import com.google.inject.Module
|
||||
import java.io.File
|
||||
import java.util.Set
|
||||
import org.eclipse.lsp4j.DidChangeWatchedFilesParams
|
||||
import org.eclipse.lsp4j.FileChangeType
|
||||
import org.eclipse.lsp4j.FileEvent
|
||||
import org.eclipse.lsp4j.WorkspaceFolder
|
||||
import org.eclipse.xtext.ide.server.IMultiRootWorkspaceConfigFactory
|
||||
import org.eclipse.xtext.ide.server.MultiRootWorkspaceConfigFactory
|
||||
import org.eclipse.xtext.ide.server.ServerModule
|
||||
import org.eclipse.xtext.util.Modules2
|
||||
import org.eclipse.xtext.workspace.FileProjectConfig
|
||||
import org.eclipse.xtext.workspace.WorkspaceConfig
|
||||
import org.junit.Test
|
||||
|
||||
import static org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Checks functionality of method IProjectConfig#isIndexOnly()
|
||||
*
|
||||
* @author Marcus Mews - Initial contribution and API
|
||||
*/
|
||||
class IndexOnlyProjectTest extends AbstractTestLangLanguageServerTest {
|
||||
|
||||
override Module getServerModule() {
|
||||
Modules2.mixin(new ServerModule, [
|
||||
bind(IMultiRootWorkspaceConfigFactory).toInstance(new MultiRootWorkspaceConfigFactory() {
|
||||
override addProjectsForWorkspaceFolder(WorkspaceConfig workspaceConfig, WorkspaceFolder workspaceFolder, Set<String> existingNames) {
|
||||
if (workspaceFolder?.uri !== null) {
|
||||
val project = new FileProjectConfig(uriExtensions.toUri(workspaceFolder.uri), getUniqueProjectName(workspaceFolder.name, existingNames)) {
|
||||
override boolean isIndexOnly() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
project.addSourceFolder(".");
|
||||
workspaceConfig.addProject(project);
|
||||
}
|
||||
}
|
||||
})
|
||||
])
|
||||
}
|
||||
|
||||
/** Shows that the resource is indexed */
|
||||
@Test
|
||||
def void testIndexByUsingReferences() {
|
||||
testReferences[
|
||||
model = '''
|
||||
type Foo {}
|
||||
type Bar {
|
||||
Foo foo
|
||||
}
|
||||
'''
|
||||
column = 'type F'.length
|
||||
expectedReferences = '''
|
||||
MyModel.testlang [[2, 1] .. [2, 4]]
|
||||
'''
|
||||
]
|
||||
}
|
||||
|
||||
/** Shows that the resource is not validated during initial build */
|
||||
@Test
|
||||
def void testInitializeBuildNoValidation() {
|
||||
'MyType1.testlang'.writeFile( '''
|
||||
type Test {
|
||||
NonExisting foo
|
||||
}
|
||||
''')
|
||||
initialize
|
||||
assertTrue(diagnostics.entrySet.join(','), diagnostics.empty)
|
||||
}
|
||||
|
||||
/** Shows that the error-free resource is not generated during initial build */
|
||||
@Test
|
||||
def void testInitializeBuildNoGeneration() {
|
||||
'MyType1.testlang'.writeFile( '''
|
||||
type TestType {
|
||||
int foo
|
||||
}
|
||||
''')
|
||||
initialize
|
||||
|
||||
val outputFile = new File(root, "src-gen/TestType.java");
|
||||
assertFalse(diagnostics.entrySet.join(','), outputFile.isFile)
|
||||
}
|
||||
|
||||
/** Shows that the resource is not validated during incremental build */
|
||||
@Test
|
||||
def void testIncrementalBuildNoValidation() {
|
||||
'MyType1.testlang'.writeFile( '''
|
||||
type Test {
|
||||
NonExisting foo
|
||||
}
|
||||
''')
|
||||
initialize
|
||||
assertTrue(diagnostics.entrySet.join(','), diagnostics.empty)
|
||||
|
||||
val path = 'MyType2.testlang'.writeFile('''
|
||||
type NonExisting {
|
||||
}
|
||||
''')
|
||||
|
||||
languageServer.getWorkspaceService.didChangeWatchedFiles(
|
||||
new DidChangeWatchedFilesParams(#[new FileEvent(path, FileChangeType.Created)])
|
||||
)
|
||||
assertTrue(diagnostics.entrySet.join(','), diagnostics.empty)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* Copyright (c) 2016, 2020 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.lsp4j.DidOpenTextDocumentParams;
|
||||
import org.eclipse.lsp4j.TextDocumentItem;
|
||||
import org.eclipse.lsp4j.jsonrpc.services.ServiceEndpoints;
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.ide.TestLangLSPExtension;
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.ide.TestLangLSPExtension.TextOfLineParam;
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.ide.TestLangLSPExtension.TextOfLineResult;
|
||||
import org.eclipse.xtext.xbase.lib.IterableExtensions;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
* @author efftinge - Initial contribution and API
|
||||
*/
|
||||
public class LspExtensionTest extends AbstractTestLangLanguageServerTest {
|
||||
@Test
|
||||
public void testExtension() throws Exception {
|
||||
String fileURI = writeFile("mydoc.testlang", "");
|
||||
initialize();
|
||||
TestLangLSPExtension ext = ServiceEndpoints.toServiceObject(languageServer, TestLangLSPExtension.class);
|
||||
DidOpenTextDocumentParams didOpenTextDocumentParams = new DidOpenTextDocumentParams();
|
||||
String text =
|
||||
"foo bar" + System.lineSeparator() +
|
||||
"baz test" + System.lineSeparator() +
|
||||
" bla blubb";
|
||||
didOpenTextDocumentParams.setTextDocument(new TextDocumentItem(fileURI, "testlang", 0, text));
|
||||
languageServer.didOpen(didOpenTextDocumentParams);
|
||||
TextOfLineParam textOfLineParam = new TextOfLineParam();
|
||||
textOfLineParam.uri = fileURI;
|
||||
textOfLineParam.line = 1;
|
||||
TextOfLineResult result = ext.getTextOfLine(textOfLineParam).get();
|
||||
Assert.assertEquals("baz test", result.text);
|
||||
Assert.assertEquals(2,
|
||||
IterableExtensions.size(Iterables.filter(Iterables.transform(notifications, n -> n.getValue()),
|
||||
TestLangLSPExtension.BuildNotification.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtension_readIndex() throws Exception {
|
||||
writeFile("model.testlang",
|
||||
"type C {\n" +
|
||||
" op baz() { }\n" +
|
||||
"}\n" +
|
||||
"type A {\n" +
|
||||
" op foo() { }\n" +
|
||||
"}\n" +
|
||||
"type B {\n" +
|
||||
" op bar() { }\n" +
|
||||
"}\n");
|
||||
initialize();
|
||||
TestLangLSPExtension ext = ServiceEndpoints.toServiceObject(languageServer, TestLangLSPExtension.class);
|
||||
List<String> actual = IterableExtensions.sort(Lists.newArrayList(ext.getAllOpNames().get()));
|
||||
Assert.assertEquals(Lists.newArrayList("bar", "baz", "foo"), actual);
|
||||
}
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.tests.server
|
||||
|
||||
import org.eclipse.lsp4j.DidOpenTextDocumentParams
|
||||
import org.eclipse.lsp4j.TextDocumentItem
|
||||
import org.eclipse.lsp4j.jsonrpc.services.ServiceEndpoints
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.ide.TestLangLSPExtension
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.ide.TestLangLSPExtension.TextOfLineParam
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.ide.TestLangLSPExtension.BuildNotification
|
||||
|
||||
/**
|
||||
* @author efftinge - Initial contribution and API
|
||||
*/
|
||||
class LspExtensionTest extends AbstractTestLangLanguageServerTest {
|
||||
|
||||
@Test def void testExtension() {
|
||||
val fileURI = "mydoc.testlang".writeFile("")
|
||||
initialize
|
||||
val ext = ServiceEndpoints.toServiceObject(languageServer, TestLangLSPExtension)
|
||||
languageServer.didOpen(new DidOpenTextDocumentParams => [
|
||||
it.textDocument = new TextDocumentItem => [
|
||||
uri = fileURI
|
||||
text = '''
|
||||
foo bar
|
||||
baz test
|
||||
bla blubb
|
||||
'''
|
||||
]
|
||||
])
|
||||
val result = ext.getTextOfLine(new TextOfLineParam => [
|
||||
uri = fileURI
|
||||
line = 1
|
||||
]).get
|
||||
Assert.assertEquals("baz test", result.text)
|
||||
Assert.assertEquals(2, notifications.map[value].filter(BuildNotification).size)
|
||||
}
|
||||
|
||||
@Test def void testExtension_readIndex() {
|
||||
'model.testlang'.writeFile('''
|
||||
type C {
|
||||
op baz() { }
|
||||
}
|
||||
type A {
|
||||
op foo() { }
|
||||
}
|
||||
type B {
|
||||
op bar() { }
|
||||
}
|
||||
''')
|
||||
initialize
|
||||
val ext = ServiceEndpoints.toServiceObject(languageServer, TestLangLSPExtension)
|
||||
val actual = ext.allOpNames.get.toList.sort
|
||||
Assert.assertEquals(#['bar', 'baz', 'foo'], actual)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/**
|
||||
* Copyright (c) 2016, 2020 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.emf.common.util.URI;
|
||||
import org.eclipse.xtext.diagnostics.Diagnostic;
|
||||
import org.eclipse.xtext.ide.server.IMultiRootWorkspaceConfigFactory;
|
||||
import org.eclipse.xtext.ide.server.MultiProjectWorkspaceConfigFactory;
|
||||
import org.eclipse.xtext.ide.server.ServerModule;
|
||||
import org.eclipse.xtext.ide.server.WorkspaceManager;
|
||||
import org.eclipse.xtext.util.CancelIndicator;
|
||||
import org.eclipse.xtext.util.Files;
|
||||
import org.eclipse.xtext.util.Modules2;
|
||||
import org.eclipse.xtext.validation.Issue;
|
||||
import org.eclipse.xtext.xbase.lib.IterableExtensions;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
/**
|
||||
* @author Jan Koehnlein - Initial contribution and API
|
||||
*/
|
||||
public class MultiProjectTest {
|
||||
private File project0;
|
||||
|
||||
private File project1;
|
||||
|
||||
private Map<URI, List<Issue>> diagnostics = new HashMap<>();
|
||||
|
||||
@Inject
|
||||
private WorkspaceManager workspaceManager;
|
||||
|
||||
@Test
|
||||
public void testCrossProjectLink() throws Exception {
|
||||
URI foo = createFile(project0, "Foo.testlang", "type Foo { Bar bar }");
|
||||
URI bar = createFile(project1, "Bar.testlang", "type Bar {}");
|
||||
workspaceManager.doBuild(Lists.newArrayList(foo, bar), Collections.emptyList(), CancelIndicator.NullImpl);
|
||||
Assert.assertEquals(2, diagnostics.size());
|
||||
Assert.assertEquals(1, diagnostics.get(foo).size());
|
||||
Assert.assertEquals(Diagnostic.LINKING_DIAGNOSTIC, Iterables.getFirst(diagnostics.get(foo), null).getCode());
|
||||
Assert.assertTrue(diagnostics.get(bar).isEmpty());
|
||||
diagnostics.clear();
|
||||
workspaceManager.getProjectManager(project0.getName()).getProjectDescription().getDependencies()
|
||||
.add(project1.getName());
|
||||
workspaceManager.doBuild(Lists.newArrayList(foo, bar), Collections.emptyList(), CancelIndicator.NullImpl);
|
||||
Assert.assertEquals(2, diagnostics.size());
|
||||
Assert.assertTrue(diagnostics.get(foo).isEmpty());
|
||||
Assert.assertTrue(diagnostics.get(bar).isEmpty());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
Injector injector = Guice.createInjector(Modules2.mixin(new ServerModule(), new AbstractModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(IMultiRootWorkspaceConfigFactory.class).to(MultiProjectWorkspaceConfigFactory.class);
|
||||
}
|
||||
}));
|
||||
injector.injectMembers(this);
|
||||
File workspaceRoot = getRoot("test-data");
|
||||
project0 = new File(workspaceRoot, "test-project0");
|
||||
project1 = new File(workspaceRoot, "test-project1");
|
||||
project0.mkdir();
|
||||
project1.mkdir();
|
||||
workspaceManager.initialize(URI.createFileURI(workspaceRoot.getAbsolutePath()),
|
||||
(URI $0, Iterable<Issue> $1) -> diagnostics.put($0, IterableExtensions.toList($1)), null);
|
||||
}
|
||||
|
||||
protected File getRoot(String path) throws Exception {
|
||||
File root = new File(path);
|
||||
if (!root.mkdirs()) {
|
||||
Files.cleanFolder(root, null, true, false);
|
||||
}
|
||||
root.deleteOnExit();
|
||||
return root;
|
||||
}
|
||||
|
||||
public URI createFile(File root, String path, CharSequence contents) throws Exception {
|
||||
File file = new File(root, path);
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
try (FileWriter fileWriter = new FileWriter(file)) {
|
||||
fileWriter.write(contents.toString());
|
||||
}
|
||||
return URI.createFileURI(file.getAbsolutePath());
|
||||
}
|
||||
}
|
|
@ -1,106 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016, 2017 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.tests.server
|
||||
|
||||
import com.google.inject.AbstractModule
|
||||
import com.google.inject.Guice
|
||||
import com.google.inject.Inject
|
||||
import java.io.File
|
||||
import java.io.FileWriter
|
||||
import java.util.List
|
||||
import java.util.Map
|
||||
import org.eclipse.emf.common.util.URI
|
||||
import org.eclipse.xtext.diagnostics.Diagnostic
|
||||
import org.eclipse.xtext.ide.server.IMultiRootWorkspaceConfigFactory
|
||||
import org.eclipse.xtext.ide.server.MultiProjectWorkspaceConfigFactory
|
||||
import org.eclipse.xtext.ide.server.ServerModule
|
||||
import org.eclipse.xtext.ide.server.WorkspaceManager
|
||||
import org.eclipse.xtext.util.CancelIndicator
|
||||
import org.eclipse.xtext.util.Files
|
||||
import org.eclipse.xtext.util.Modules2
|
||||
import org.eclipse.xtext.validation.Issue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
import static org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* @author Jan Koehnlein - Initial contribution and API
|
||||
*/
|
||||
class MultiProjectTest {
|
||||
|
||||
File project0
|
||||
File project1
|
||||
Map<URI, List<Issue>> diagnostics = newHashMap
|
||||
|
||||
@Inject WorkspaceManager workspaceManager
|
||||
|
||||
@Test
|
||||
def void testCrossProjectLink() {
|
||||
val foo = createFile(project0, 'Foo.testlang', '''
|
||||
type Foo {
|
||||
Bar bar
|
||||
}
|
||||
''')
|
||||
val bar = createFile(project1, 'Bar.testlang', '''
|
||||
type Bar {
|
||||
}
|
||||
''')
|
||||
workspaceManager.doBuild(#[foo, bar], emptyList, CancelIndicator.NullImpl)
|
||||
assertEquals(2, diagnostics.size)
|
||||
assertEquals(1, diagnostics.get(foo).size)
|
||||
assertEquals(Diagnostic.LINKING_DIAGNOSTIC, diagnostics.get(foo).head.code)
|
||||
assertTrue(diagnostics.get(bar).empty)
|
||||
|
||||
// add a dependency from project0 to project1
|
||||
diagnostics.clear
|
||||
workspaceManager.getProjectManager(project0.name).projectDescription.dependencies += project1.name
|
||||
workspaceManager.doBuild(#[foo, bar], emptyList, CancelIndicator.NullImpl)
|
||||
assertEquals(2, diagnostics.size)
|
||||
assertTrue(diagnostics.get(foo).empty)
|
||||
assertTrue(diagnostics.get(bar).empty)
|
||||
}
|
||||
|
||||
@Before
|
||||
def void setup() {
|
||||
val injector = Guice.createInjector(Modules2.mixin(new ServerModule, new AbstractModule() {
|
||||
override protected configure() {
|
||||
bind(IMultiRootWorkspaceConfigFactory).to(MultiProjectWorkspaceConfigFactory)
|
||||
}
|
||||
}))
|
||||
injector.injectMembers(this)
|
||||
val workspaceRoot = getRoot("test-data")
|
||||
project0 = new File(workspaceRoot, "test-project0")
|
||||
project1 = new File(workspaceRoot, "test-project1")
|
||||
project0.mkdir
|
||||
project1.mkdir
|
||||
workspaceManager.initialize(URI.createFileURI(workspaceRoot.absolutePath), [diagnostics.put($0, $1.toList)], null)
|
||||
}
|
||||
|
||||
protected def getRoot(String path) {
|
||||
val root = new File(path)
|
||||
if (!root.mkdirs) {
|
||||
Files.cleanFolder(root, null, true, false)
|
||||
}
|
||||
root.deleteOnExit
|
||||
root
|
||||
}
|
||||
|
||||
def URI createFile(File root, String path, CharSequence contents) {
|
||||
val file = new File(root, path)
|
||||
file.parentFile.mkdirs
|
||||
file.createNewFile
|
||||
new FileWriter(file) => [
|
||||
write(contents.toString)
|
||||
close
|
||||
]
|
||||
return URI.createFileURI(file.absolutePath)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/**
|
||||
* Copyright (c) 2016, 2020 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import org.eclipse.lsp4j.DidChangeTextDocumentParams;
|
||||
import org.eclipse.lsp4j.DidChangeWatchedFilesParams;
|
||||
import org.eclipse.lsp4j.FileChangeType;
|
||||
import org.eclipse.lsp4j.FileEvent;
|
||||
import org.eclipse.lsp4j.Position;
|
||||
import org.eclipse.lsp4j.Range;
|
||||
import org.eclipse.lsp4j.TextDocumentContentChangeEvent;
|
||||
import org.eclipse.lsp4j.VersionedTextDocumentIdentifier;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
* @author Sven Efftinge - Initial contribution and API
|
||||
*/
|
||||
public class OpenDocumentTest extends AbstractTestLangLanguageServerTest {
|
||||
@Test
|
||||
public void testOpenedDocumentShadowsPersistedFile() {
|
||||
String model =
|
||||
"type Test {\n" +
|
||||
" NonExisting foo\n" +
|
||||
"}";
|
||||
String firstFile = writeFile("MyType1.testlang", model);
|
||||
initialize();
|
||||
assertEquals("Couldn't resolve reference to TypeDeclaration 'NonExisting'.",
|
||||
Iterables.getFirst(getDiagnostics().get(firstFile), null).getMessage());
|
||||
String path = writeFile("MyType2.testlang", "\n type Foo {\n }\n ");
|
||||
languageServer.getWorkspaceService().didChangeWatchedFiles(new DidChangeWatchedFilesParams(
|
||||
Lists.newArrayList(new FileEvent(path, FileChangeType.Created))));
|
||||
assertEquals("Couldn't resolve reference to TypeDeclaration 'NonExisting'.",
|
||||
Iterables.getFirst(getDiagnostics().get(firstFile), null).getMessage());
|
||||
String model2 = "type NonExisting {}";
|
||||
open(path, model2);
|
||||
Assert.assertNull(Iterables.getFirst(getDiagnostics().get(firstFile), null));
|
||||
close(path);
|
||||
assertEquals("Couldn't resolve reference to TypeDeclaration 'NonExisting'.",
|
||||
Iterables.getFirst(getDiagnostics().get(firstFile), null).getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDidChange() {
|
||||
String model =
|
||||
"type Test {\n" +
|
||||
" NonExisting foo\n" +
|
||||
"}\n";
|
||||
String firstFile = writeFile("MyType1.testlang",
|
||||
model);
|
||||
initialize();
|
||||
assertEquals("Couldn't resolve reference to TypeDeclaration 'NonExisting'.",
|
||||
Iterables.getFirst(getDiagnostics().get(firstFile), null).getMessage());
|
||||
open(firstFile, model);
|
||||
assertEquals("Couldn't resolve reference to TypeDeclaration 'NonExisting'.",
|
||||
Iterables.getFirst(getDiagnostics().get(firstFile), null).getMessage());
|
||||
DidChangeTextDocumentParams didChangeTextDocumentParams = new DidChangeTextDocumentParams();
|
||||
didChangeTextDocumentParams.setTextDocument(new VersionedTextDocumentIdentifier(firstFile, 2));
|
||||
TextDocumentContentChangeEvent textDocumentContentChangeEvent = new TextDocumentContentChangeEvent("Test");
|
||||
textDocumentContentChangeEvent.setRange(new Range(new Position(1, 4), new Position(1, 15)));
|
||||
didChangeTextDocumentParams.setContentChanges(Lists.newArrayList(textDocumentContentChangeEvent));
|
||||
languageServer.didChange(didChangeTextDocumentParams);
|
||||
Assert.assertNull(Iterables.getFirst(getDiagnostics().get(firstFile), null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDidClose() {
|
||||
String fileURI = writeFile("Foo.testlang", "");
|
||||
initialize();
|
||||
String referencingFileURI = getVirtualFile("Bar.testlang");
|
||||
String model =
|
||||
"type Bar {\n" +
|
||||
" Foo foo\n" +
|
||||
"}\n";
|
||||
open(referencingFileURI, model);
|
||||
Assert.assertFalse(getDiagnostics().get(referencingFileURI).isEmpty());
|
||||
open(fileURI, "type Foo {}");
|
||||
Assert.assertTrue(getDiagnostics().get(referencingFileURI).isEmpty());
|
||||
close(fileURI);
|
||||
Assert.assertFalse(getDiagnostics().get(referencingFileURI).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDidCloseInMemory() {
|
||||
initialize();
|
||||
String fileURI = getVirtualFile("Foo.testlang");
|
||||
open(fileURI, "type Foo {}");
|
||||
String referencingFileURI = getVirtualFile("Bar.testlang");
|
||||
String model =
|
||||
"type Bar {\n" +
|
||||
" Foo foo\n" +
|
||||
"}\n";
|
||||
open(referencingFileURI, model);
|
||||
Assert.assertTrue(getDiagnostics().get(referencingFileURI).isEmpty());
|
||||
close(fileURI);
|
||||
Assert.assertFalse(getDiagnostics().get(referencingFileURI).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInMemory_GH_456() {
|
||||
initialize();
|
||||
String uri = "inmemory:/foo/bar.testlang";
|
||||
open(uri, "type Foo { }");
|
||||
Assert.assertNotNull("Diagnostics could be empty but never null.", getDiagnostics().get(uri));
|
||||
}
|
||||
}
|
|
@ -1,147 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016, 2017 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.tests.server
|
||||
|
||||
import org.eclipse.lsp4j.DidChangeTextDocumentParams
|
||||
import org.eclipse.lsp4j.DidChangeWatchedFilesParams
|
||||
import org.eclipse.lsp4j.FileChangeType
|
||||
import org.eclipse.lsp4j.FileEvent
|
||||
import org.eclipse.lsp4j.Position
|
||||
import org.eclipse.lsp4j.Range
|
||||
import org.eclipse.lsp4j.TextDocumentContentChangeEvent
|
||||
import org.eclipse.lsp4j.VersionedTextDocumentIdentifier
|
||||
import org.junit.Test
|
||||
|
||||
import static org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* @author Sven Efftinge - Initial contribution and API
|
||||
*/
|
||||
class OpenDocumentTest extends AbstractTestLangLanguageServerTest {
|
||||
|
||||
@Test
|
||||
def void testOpenedDocumentShadowsPersistedFile() {
|
||||
val firstFile = 'MyType1.testlang'.writeFile( '''
|
||||
type Test {
|
||||
NonExisting foo
|
||||
}
|
||||
''')
|
||||
initialize
|
||||
|
||||
assertEquals("Couldn't resolve reference to TypeDeclaration 'NonExisting'.", diagnostics.get(firstFile).head.message)
|
||||
|
||||
val path = 'MyType2.testlang'.writeFile( '''
|
||||
type Foo {
|
||||
}
|
||||
''')
|
||||
languageServer.getWorkspaceService.didChangeWatchedFiles(
|
||||
new DidChangeWatchedFilesParams(#[
|
||||
new FileEvent(path, FileChangeType.Created)
|
||||
])
|
||||
)
|
||||
|
||||
// still erroneous
|
||||
assertEquals("Couldn't resolve reference to TypeDeclaration 'NonExisting'.", diagnostics.get(firstFile).head.message)
|
||||
|
||||
// let's open the document with a different content
|
||||
open(path, '''
|
||||
type NonExisting {
|
||||
}
|
||||
''')
|
||||
assertNull(diagnostics.get(firstFile).head)
|
||||
|
||||
// let's close again
|
||||
close(path)
|
||||
assertEquals("Couldn't resolve reference to TypeDeclaration 'NonExisting'.", diagnostics.get(firstFile).head.message)
|
||||
}
|
||||
|
||||
@Test
|
||||
def void testDidChange() {
|
||||
val firstFile = 'MyType1.testlang'.writeFile( '''
|
||||
type Test {
|
||||
NonExisting foo
|
||||
}
|
||||
''')
|
||||
initialize
|
||||
|
||||
assertEquals("Couldn't resolve reference to TypeDeclaration 'NonExisting'.", diagnostics.get(firstFile).head.message)
|
||||
|
||||
open(firstFile, '''
|
||||
type Test {
|
||||
NonExisting foo
|
||||
}
|
||||
''')
|
||||
assertEquals("Couldn't resolve reference to TypeDeclaration 'NonExisting'.", diagnostics.get(firstFile).head.message)
|
||||
|
||||
languageServer.didChange(new DidChangeTextDocumentParams => [
|
||||
textDocument = new VersionedTextDocumentIdentifier => [
|
||||
uri = firstFile
|
||||
version = 2
|
||||
]
|
||||
contentChanges = #[
|
||||
new TextDocumentContentChangeEvent => [
|
||||
range = new Range(new Position(1, 4), new Position(1, 15))
|
||||
text = "Test"
|
||||
]
|
||||
]
|
||||
])
|
||||
assertNull(diagnostics.get(firstFile).head)
|
||||
}
|
||||
|
||||
@Test
|
||||
def void testDidClose() {
|
||||
val fileURI = 'Foo.testlang'.writeFile('')
|
||||
initialize
|
||||
|
||||
val referencingFileURI = 'Bar.testlang'.virtualFile
|
||||
referencingFileURI.open('''
|
||||
type Bar {
|
||||
Foo foo
|
||||
}
|
||||
''')
|
||||
assertFalse(diagnostics.get(referencingFileURI).empty)
|
||||
|
||||
|
||||
fileURI.open('type Foo {}')
|
||||
assertTrue(diagnostics.get(referencingFileURI).empty)
|
||||
|
||||
close(fileURI);
|
||||
assertFalse(diagnostics.get(referencingFileURI).empty)
|
||||
}
|
||||
|
||||
@Test
|
||||
def void testDidCloseInMemory() {
|
||||
initialize
|
||||
|
||||
val fileURI = 'Foo.testlang'.virtualFile
|
||||
fileURI.open('type Foo {}')
|
||||
|
||||
val referencingFileURI = 'Bar.testlang'.virtualFile
|
||||
referencingFileURI.open('''
|
||||
type Bar {
|
||||
Foo foo
|
||||
}
|
||||
''')
|
||||
assertTrue(diagnostics.get(referencingFileURI).empty)
|
||||
|
||||
close(fileURI);
|
||||
assertFalse(diagnostics.get(referencingFileURI).empty)
|
||||
}
|
||||
|
||||
@Test
|
||||
def void testInMemory_GH_456() {
|
||||
initialize
|
||||
val uri = 'inmemory:/foo/bar.testlang';
|
||||
open(uri, '''
|
||||
type Foo { }
|
||||
''');
|
||||
assertNotNull('''Diagnostics could be empty but never null.''', diagnostics.get(uri));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
* Copyright (c) 2016, 2020 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import org.eclipse.xtext.testing.ReferenceTestConfiguration;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
/**
|
||||
* @author kosyakov - Initial contribution and API
|
||||
*/
|
||||
public class ReferenceTest extends AbstractTestLangLanguageServerTest {
|
||||
@Test
|
||||
public void testReferences_01() {
|
||||
testReferences((ReferenceTestConfiguration it) -> {
|
||||
String model =
|
||||
"type Foo {}\n" +
|
||||
"type Bar {\n" +
|
||||
" Foo foo\n" +
|
||||
"}";
|
||||
it.setModel(model);
|
||||
it.setColumn("type F".length());
|
||||
it.setExpectedReferences("MyModel.testlang [[2, 1] .. [2, 4]]\n");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReferences_02() {
|
||||
testReferences((ReferenceTestConfiguration it) -> {
|
||||
String model =
|
||||
"type Foo {}\n" +
|
||||
"type Bar {\n" +
|
||||
" Foo foo\n" +
|
||||
"}";
|
||||
it.setModel(model);
|
||||
it.setColumn("type F".length());
|
||||
it.setIncludeDeclaration(true);
|
||||
it.setExpectedReferences(
|
||||
"MyModel.testlang [[0, 5] .. [0, 8]]\n" +
|
||||
"MyModel.testlang [[2, 1] .. [2, 4]]\n");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReferences_03_acrossFiles() {
|
||||
testReferences((ReferenceTestConfiguration it) -> {
|
||||
it.setFilesInScope(ImmutableMap.<String, CharSequence>builder().put("foo.testlang", "type Foo {}").build());
|
||||
String model =
|
||||
"type Bar {\n" +
|
||||
" Foo foo" +
|
||||
"}\n";
|
||||
it.setModel(model);
|
||||
it.setLine(1);
|
||||
it.setColumn(6);
|
||||
it.setIncludeDeclaration(true);
|
||||
it.setExpectedReferences(
|
||||
"foo.testlang [[0, 5] .. [0, 8]]\n" +
|
||||
"MyModel.testlang [[1, 4] .. [1, 7]]\n");
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.tests.server
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* @author kosyakov - Initial contribution and API
|
||||
*/
|
||||
class ReferenceTest extends AbstractTestLangLanguageServerTest {
|
||||
|
||||
@Test
|
||||
def void testReferences_01() {
|
||||
testReferences[
|
||||
model = '''
|
||||
type Foo {}
|
||||
type Bar {
|
||||
Foo foo
|
||||
}
|
||||
'''
|
||||
column = 'type F'.length
|
||||
expectedReferences = '''
|
||||
MyModel.testlang [[2, 1] .. [2, 4]]
|
||||
'''
|
||||
]
|
||||
}
|
||||
|
||||
@Test
|
||||
def void testReferences_02() {
|
||||
testReferences[
|
||||
model = '''
|
||||
type Foo {}
|
||||
type Bar {
|
||||
Foo foo
|
||||
}
|
||||
'''
|
||||
column = 'type F'.length
|
||||
includeDeclaration = true
|
||||
expectedReferences = '''
|
||||
MyModel.testlang [[0, 5] .. [0, 8]]
|
||||
MyModel.testlang [[2, 1] .. [2, 4]]
|
||||
'''
|
||||
]
|
||||
}
|
||||
|
||||
@Test
|
||||
def void testReferences_03_acrossFiles() {
|
||||
testReferences[
|
||||
filesInScope = #{
|
||||
"foo.testlang" -> '''
|
||||
type Foo {}
|
||||
'''
|
||||
}
|
||||
model = '''
|
||||
type Bar {
|
||||
Foo foo
|
||||
}
|
||||
'''
|
||||
line = 1
|
||||
column = 6
|
||||
includeDeclaration = true
|
||||
expectedReferences = '''
|
||||
foo.testlang [[0, 5] .. [0, 8]]
|
||||
MyModel.testlang [[1, 4] .. [1, 7]]
|
||||
'''
|
||||
]
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
/**
|
||||
* Copyright (c) 2016, 2020 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.eclipse.lsp4j.DefinitionParams;
|
||||
import org.eclipse.lsp4j.Diagnostic;
|
||||
import org.eclipse.lsp4j.DidChangeWatchedFilesParams;
|
||||
import org.eclipse.lsp4j.FileChangeType;
|
||||
import org.eclipse.lsp4j.FileEvent;
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
import org.eclipse.lsp4j.jsonrpc.ResponseErrorException;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.ResponseErrorCode;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
* @author Sven Efftinge - Initial contribution and API
|
||||
*/
|
||||
public class ServerTest extends AbstractTestLangLanguageServerTest {
|
||||
@Test
|
||||
public void testInitializeBuild() {
|
||||
String model =
|
||||
"type Test {\n" +
|
||||
" string foo\n" +
|
||||
"}\n";
|
||||
writeFile("MyType1.testlang", model);
|
||||
initialize();
|
||||
Assert.assertTrue(Joiner.on(",").join(getDiagnostics().entrySet()),
|
||||
Iterables.getFirst(getDiagnostics().values(), null).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitializeBuildWithError() {
|
||||
String model =
|
||||
"type Test {\n" +
|
||||
" NonExisting foo\n" +
|
||||
"}\n";
|
||||
writeFile("MyType1.testlang", model);
|
||||
initialize();
|
||||
Diagnostic firstDiagnostic = getFirstDiagnostic();
|
||||
assertEquals("Couldn't resolve reference to TypeDeclaration 'NonExisting'.", firstDiagnostic.getMessage());
|
||||
Assert.assertEquals(1, firstDiagnostic.getRange().getStart().getLine());
|
||||
Assert.assertEquals(4, firstDiagnostic.getRange().getStart().getCharacter());
|
||||
Assert.assertEquals(1, firstDiagnostic.getRange().getEnd().getLine());
|
||||
Assert.assertEquals(15, firstDiagnostic.getRange().getEnd().getCharacter());
|
||||
}
|
||||
|
||||
private Diagnostic getFirstDiagnostic() {
|
||||
return Iterables.getFirst(Iterables.getFirst(getDiagnostics().values(), null), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPublishDiagnosticsAfterInitialized() {
|
||||
String model =
|
||||
"type Test {\n" +
|
||||
" NonExisting foo\n" +
|
||||
"}\n";
|
||||
writeFile("MyType1.testlang", model);
|
||||
initialize(null, false);
|
||||
Assert.assertTrue("Diagnostics produced before 'initialized' was called", getDiagnostics().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncrementalBuildWithError() {
|
||||
String model =
|
||||
"type Test {\n" +
|
||||
" NonExisting foo\n" +
|
||||
"}\n";
|
||||
writeFile("MyType1.testlang", model);
|
||||
initialize();
|
||||
assertEquals("Couldn't resolve reference to TypeDeclaration 'NonExisting'.", getFirstDiagnostic().getMessage());
|
||||
String model2 =
|
||||
"type NonExisting {\n" +
|
||||
"}\n";
|
||||
String path = writeFile("MyType2.testlang", model2);
|
||||
languageServer.getWorkspaceService().didChangeWatchedFiles(
|
||||
new DidChangeWatchedFilesParams(Lists.newArrayList(new FileEvent(path, FileChangeType.Created))));
|
||||
Assert.assertNotNull(getDiagnostics().get(path));
|
||||
for (List<Diagnostic> d : getDiagnostics().values()) {
|
||||
Assert.assertTrue(Joiner.on(",").join(d), d.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncrementalDeletion() {
|
||||
String model =
|
||||
"type Test {\n" +
|
||||
" NonExisting foo\n" +
|
||||
"}\n";
|
||||
String path = writeFile("MyType1.testlang", model);
|
||||
initialize();
|
||||
assertEquals("Couldn't resolve reference to TypeDeclaration 'NonExisting'.", getFirstDiagnostic().getMessage());
|
||||
deleteFile("MyType1.testlang");
|
||||
languageServer.getWorkspaceService().didChangeWatchedFiles(
|
||||
new DidChangeWatchedFilesParams(Lists.newArrayList(new FileEvent(path, FileChangeType.Deleted))));
|
||||
Assert.assertTrue(Iterables.getFirst(getDiagnostics().values(), null).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTwoFilesDeleteClose() {
|
||||
String fileURI = writeFile("Foo.testlang", "");
|
||||
initialize();
|
||||
String referencingFileURI = getVirtualFile("Bar.testlang");
|
||||
String model =
|
||||
"type Bar {\n" +
|
||||
" Foo foo\n" +
|
||||
"}\n";
|
||||
open(referencingFileURI, model);
|
||||
Assert.assertFalse("Bar.testlang references missing type Foo from Foo.testlang: expect error",
|
||||
getDiagnostics().get(referencingFileURI).isEmpty());
|
||||
open(fileURI, "type Foo {}");
|
||||
Assert.assertTrue("Bar.testlang references type Foo from Foo.testlang: expect no error",
|
||||
getDiagnostics().get(referencingFileURI).isEmpty());
|
||||
deleteFile(fileURI);
|
||||
languageServer.getWorkspaceService().didChangeWatchedFiles(
|
||||
new DidChangeWatchedFilesParams(Lists.newArrayList(new FileEvent(fileURI, FileChangeType.Deleted))));
|
||||
Assert.assertTrue("delete file on disk: expect no error", getDiagnostics().get(referencingFileURI).isEmpty());
|
||||
close(fileURI);
|
||||
Assert.assertFalse("close deleted file: expect error", getDiagnostics().get(referencingFileURI).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingInitialize() throws Exception {
|
||||
try {
|
||||
DefinitionParams definitionParams = new DefinitionParams();
|
||||
definitionParams.setTextDocument(new TextDocumentIdentifier("file:/home/test/workspace/mydoc.testlang"));
|
||||
languageServer.definition(definitionParams).get();
|
||||
Assert.fail("Expected a ResponseErrorException");
|
||||
} catch (ExecutionException exception) {
|
||||
Assert.assertEquals(ResponseErrorCode.serverNotInitialized.getValue(),
|
||||
((ResponseErrorException) exception.getCause()).getResponseError().getCode());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,147 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016, 2017 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.tests.server
|
||||
|
||||
import java.util.concurrent.ExecutionException
|
||||
import org.eclipse.lsp4j.DidChangeWatchedFilesParams
|
||||
import org.eclipse.lsp4j.FileChangeType
|
||||
import org.eclipse.lsp4j.FileEvent
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier
|
||||
import org.eclipse.lsp4j.jsonrpc.ResponseErrorException
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.ResponseErrorCode
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
|
||||
import static org.junit.Assert.*
|
||||
import org.eclipse.lsp4j.DefinitionParams
|
||||
|
||||
/**
|
||||
* @author Sven Efftinge - Initial contribution and API
|
||||
*/
|
||||
class ServerTest extends AbstractTestLangLanguageServerTest {
|
||||
|
||||
@Test
|
||||
def void testInitializeBuild() {
|
||||
'MyType1.testlang'.writeFile('''
|
||||
type Test {
|
||||
string foo
|
||||
}
|
||||
''')
|
||||
initialize
|
||||
assertTrue(diagnostics.entrySet.join(','), diagnostics.values.head.empty)
|
||||
}
|
||||
|
||||
@Test
|
||||
def void testInitializeBuildWithError() {
|
||||
'MyType1.testlang'.writeFile( '''
|
||||
type Test {
|
||||
NonExisting foo
|
||||
}
|
||||
''')
|
||||
initialize
|
||||
assertEquals("Couldn't resolve reference to TypeDeclaration 'NonExisting'.", diagnostics.values.head.head?.message)
|
||||
assertEquals(1, diagnostics.values.head.head.range.start.line)
|
||||
assertEquals(4, diagnostics.values.head.head.range.start.character)
|
||||
assertEquals(1, diagnostics.values.head.head.range.end.line)
|
||||
assertEquals(15, diagnostics.values.head.head.range.end.character)
|
||||
}
|
||||
|
||||
@Test
|
||||
def void testPublishDiagnosticsAfterInitialized() {
|
||||
'MyType1.testlang'.writeFile( '''
|
||||
type Test {
|
||||
NonExisting foo
|
||||
}
|
||||
''')
|
||||
initialize(null, false)
|
||||
assertTrue("Diagnostics produced before 'initialized' was called", diagnostics.empty)
|
||||
}
|
||||
|
||||
@Test
|
||||
def void testIncrementalBuildWithError() {
|
||||
'MyType1.testlang'.writeFile( '''
|
||||
type Test {
|
||||
NonExisting foo
|
||||
}
|
||||
''')
|
||||
initialize
|
||||
assertEquals("Couldn't resolve reference to TypeDeclaration 'NonExisting'.", diagnostics.values.head.head.message)
|
||||
|
||||
val path = 'MyType2.testlang'.writeFile('''
|
||||
type NonExisting {
|
||||
}
|
||||
''')
|
||||
|
||||
languageServer.getWorkspaceService.didChangeWatchedFiles(
|
||||
new DidChangeWatchedFilesParams(#[new FileEvent(path, FileChangeType.Created)])
|
||||
)
|
||||
assertNotNull(diagnostics.get(path))
|
||||
assertTrue(diagnostics.values.join(','), diagnostics.values.forall[empty])
|
||||
}
|
||||
|
||||
@Test
|
||||
def void testIncrementalDeletion() {
|
||||
val path = 'MyType1.testlang'.writeFile( '''
|
||||
type Test {
|
||||
NonExisting foo
|
||||
}
|
||||
''')
|
||||
initialize
|
||||
assertEquals("Couldn't resolve reference to TypeDeclaration 'NonExisting'.",
|
||||
diagnostics.values.head.head.message)
|
||||
'MyType1.testlang'.deleteFile
|
||||
languageServer.getWorkspaceService.didChangeWatchedFiles(
|
||||
new DidChangeWatchedFilesParams(#[new FileEvent(path, FileChangeType.Deleted)])
|
||||
)
|
||||
assertTrue(diagnostics.values.head.empty)
|
||||
}
|
||||
|
||||
@Test
|
||||
def void testTwoFilesDeleteClose() {
|
||||
// create two files with cross ref
|
||||
val fileURI = 'Foo.testlang'.writeFile('')
|
||||
initialize
|
||||
val referencingFileURI = 'Bar.testlang'.virtualFile
|
||||
referencingFileURI.open('''
|
||||
type Bar {
|
||||
Foo foo
|
||||
}
|
||||
''')
|
||||
assertFalse("Bar.testlang references missing type Foo from Foo.testlang: expect error",
|
||||
diagnostics.get(referencingFileURI).empty)
|
||||
fileURI.open('type Foo {}')
|
||||
// no errors
|
||||
assertTrue("Bar.testlang references type Foo from Foo.testlang: expect no error",
|
||||
diagnostics.get(referencingFileURI).empty)
|
||||
|
||||
fileURI.deleteFile
|
||||
languageServer.getWorkspaceService.didChangeWatchedFiles(
|
||||
new DidChangeWatchedFilesParams(#[new FileEvent(fileURI, FileChangeType.Deleted)])
|
||||
)
|
||||
assertTrue("delete file on disk: expect no error", diagnostics.get(referencingFileURI).empty)
|
||||
close(fileURI);
|
||||
assertFalse("close deleted file: expect error", diagnostics.get(referencingFileURI).empty)
|
||||
}
|
||||
|
||||
@Test
|
||||
def void testMissingInitialize() {
|
||||
try {
|
||||
languageServer.definition(new DefinitionParams => [
|
||||
textDocument = new TextDocumentIdentifier => [
|
||||
uri = 'file:/home/test/workspace/mydoc.testlang'
|
||||
]
|
||||
]).get
|
||||
Assert.fail("Expected a ResponseErrorException")
|
||||
} catch (ExecutionException exception) {
|
||||
Assert.assertEquals(ResponseErrorCode.serverNotInitialized.value, (exception.cause as ResponseErrorException).responseError.code)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
/**
|
||||
* Copyright (c) 2020 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.eclipse.lsp4j.DidChangeWorkspaceFoldersParams;
|
||||
import org.eclipse.lsp4j.InitializeParams;
|
||||
import org.eclipse.lsp4j.WorkspaceFolder;
|
||||
import org.eclipse.lsp4j.WorkspaceFoldersChangeEvent;
|
||||
import org.eclipse.xtext.ide.server.ILanguageServerAccess;
|
||||
import org.eclipse.xtext.ide.server.UriExtensions;
|
||||
import org.eclipse.xtext.ide.server.WorkspaceManager;
|
||||
import org.eclipse.xtext.resource.IResourceDescription;
|
||||
import org.eclipse.xtext.util.Modules2;
|
||||
import org.eclipse.xtext.xbase.lib.Procedures.Procedure0;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Scopes;
|
||||
|
||||
/**
|
||||
* @author Jan Koehnlein - Initial contribution and API
|
||||
*/
|
||||
public class WorkspaceFoldersTest extends AbstractTestLangLanguageServerTest {
|
||||
@Inject
|
||||
private UriExtensions uriExtensions;
|
||||
|
||||
@Inject
|
||||
private WorkspaceManager workspaceManager;
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
@Test
|
||||
public void testInitialize() throws Exception {
|
||||
File rootFolder1 = temporaryFolder.newFolder("root1");
|
||||
File rootFolder2 = temporaryFolder.newFolder("root2");
|
||||
writeFile(rootFolder1, "one.testlang", "type Foo { Bar bar }");
|
||||
String twoUri = writeFile(rootFolder2, "two.testlang", "type Bar { Foo foo }");
|
||||
initialize((InitializeParams it) -> {
|
||||
it.setWorkspaceFolders(
|
||||
Lists.newArrayList(new WorkspaceFolder(uriExtensions.toUriString(rootFolder1.toURI()), "root1"),
|
||||
new WorkspaceFolder(uriExtensions.toUriString(rootFolder2.toURI()), "root2")));
|
||||
});
|
||||
Assert.assertEquals(2, getDiagnostics().size());
|
||||
Assert.assertEquals(1, getDiagnostics().get(twoUri).size());
|
||||
withBuild(() -> {
|
||||
DidChangeWorkspaceFoldersParams didChangeWorkspaceFoldersParams = new DidChangeWorkspaceFoldersParams();
|
||||
WorkspaceFoldersChangeEvent workspaceFoldersChangeEvent = new WorkspaceFoldersChangeEvent();
|
||||
workspaceFoldersChangeEvent.setRemoved(
|
||||
Lists.newArrayList(new WorkspaceFolder(uriExtensions.toUriString(rootFolder2.toURI()), "root2")));
|
||||
didChangeWorkspaceFoldersParams.setEvent(workspaceFoldersChangeEvent);
|
||||
languageServer.didChangeWorkspaceFolders(didChangeWorkspaceFoldersParams);
|
||||
});
|
||||
Assert.assertEquals(0, getDiagnostics().get(twoUri).size());
|
||||
withBuild(() -> {
|
||||
DidChangeWorkspaceFoldersParams didChangeWorkspaceFoldersParams = new DidChangeWorkspaceFoldersParams();
|
||||
WorkspaceFoldersChangeEvent workspaceFoldersChangeEvent = new WorkspaceFoldersChangeEvent();
|
||||
workspaceFoldersChangeEvent.setAdded(
|
||||
Lists.newArrayList(new WorkspaceFolder(uriExtensions.toUriString(rootFolder2.toURI()), "root2")));
|
||||
didChangeWorkspaceFoldersParams.setEvent(workspaceFoldersChangeEvent);
|
||||
languageServer.didChangeWorkspaceFolders(didChangeWorkspaceFoldersParams);
|
||||
});
|
||||
Assert.assertEquals(1, getDiagnostics().get(twoUri).size());
|
||||
}
|
||||
|
||||
protected void withBuild(Procedure0 lambda) throws Exception {
|
||||
CompletableFuture<Void> future = new CompletableFuture<Void>();
|
||||
workspaceManager.addBuildListener(new ILanguageServerAccess.IBuildListener() {
|
||||
@Override
|
||||
public void afterBuild(List<IResourceDescription.Delta> it) {
|
||||
workspaceManager.removeBuildListener(this);
|
||||
future.complete(null);
|
||||
}
|
||||
});
|
||||
lambda.apply();
|
||||
future.get();
|
||||
}
|
||||
|
||||
public String writeFile(File root, String path, CharSequence contents) throws Exception {
|
||||
File file = new File(root, path);
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
FileWriter writer = new FileWriter(file);
|
||||
writer.write(contents.toString());
|
||||
writer.close();
|
||||
return uriExtensions.toUriString(file.toURI().normalize());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected com.google.inject.Module getServerModule() {
|
||||
com.google.inject.Module defaultModule = super.getServerModule();
|
||||
com.google.inject.Module customModule = new AbstractModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(WorkspaceManager.class).in(Scopes.SINGLETON);
|
||||
}
|
||||
};
|
||||
return Modules2.mixin(defaultModule, customModule);
|
||||
}
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2020 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.tests.server
|
||||
|
||||
import com.google.inject.AbstractModule
|
||||
import com.google.inject.Inject
|
||||
import com.google.inject.Module
|
||||
import com.google.inject.Scopes
|
||||
import java.io.File
|
||||
import java.io.FileWriter
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import org.eclipse.lsp4j.DidChangeWorkspaceFoldersParams
|
||||
import org.eclipse.lsp4j.WorkspaceFolder
|
||||
import org.eclipse.lsp4j.WorkspaceFoldersChangeEvent
|
||||
import org.eclipse.xtext.ide.server.UriExtensions
|
||||
import org.eclipse.xtext.ide.server.WorkspaceManager
|
||||
import org.eclipse.xtext.util.Modules2
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TemporaryFolder
|
||||
|
||||
import static org.junit.Assert.assertEquals
|
||||
|
||||
/**
|
||||
* @author Jan Koehnlein - Initial contribution and API
|
||||
*/
|
||||
class WorkspaceFoldersTest extends AbstractTestLangLanguageServerTest {
|
||||
|
||||
@Inject extension UriExtensions
|
||||
|
||||
@Inject WorkspaceManager workspaceManager
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder()
|
||||
|
||||
@Test
|
||||
def void testInitialize() {
|
||||
val rootFolder1 = temporaryFolder.newFolder('root1')
|
||||
val rootFolder2 = temporaryFolder.newFolder('root2')
|
||||
writeFile(rootFolder1, "one.testlang", '''
|
||||
type Foo {
|
||||
Bar bar
|
||||
}
|
||||
''')
|
||||
val twoUri = writeFile(rootFolder2, "two.testlang", '''
|
||||
type Bar {
|
||||
Foo foo
|
||||
}
|
||||
''')
|
||||
initialize[
|
||||
workspaceFolders = #[
|
||||
new WorkspaceFolder(rootFolder1.toURI.toUriString, 'root1'),
|
||||
new WorkspaceFolder(rootFolder2.toURI.toUriString, 'root2')
|
||||
]
|
||||
]
|
||||
assertEquals(2, diagnostics.size)
|
||||
assertEquals(1, diagnostics.get(twoUri).size)
|
||||
withBuild [
|
||||
languageServer.didChangeWorkspaceFolders(new DidChangeWorkspaceFoldersParams => [
|
||||
event = new WorkspaceFoldersChangeEvent => [
|
||||
removed = #[
|
||||
new WorkspaceFolder(rootFolder2.toURI.toUriString, 'root2')
|
||||
]
|
||||
]
|
||||
])
|
||||
]
|
||||
assertEquals(0, diagnostics.get(twoUri).size)
|
||||
withBuild [
|
||||
languageServer.didChangeWorkspaceFolders(new DidChangeWorkspaceFoldersParams => [
|
||||
event = new WorkspaceFoldersChangeEvent => [
|
||||
added = #[
|
||||
new WorkspaceFolder(rootFolder2.toURI.toUriString, 'root2')
|
||||
]
|
||||
]
|
||||
])
|
||||
]
|
||||
assertEquals(1, diagnostics.get(twoUri).size)
|
||||
}
|
||||
|
||||
protected def void withBuild(()=>void lambda) {
|
||||
val future = new CompletableFuture<Void>()
|
||||
workspaceManager.addBuildListener[
|
||||
workspaceManager.removeBuildListener(self)
|
||||
future.complete(null)
|
||||
]
|
||||
lambda.apply
|
||||
future.get
|
||||
}
|
||||
|
||||
def String writeFile(File root, String path, CharSequence contents) {
|
||||
val file = new File(root, path)
|
||||
file.parentFile.mkdirs
|
||||
file.createNewFile
|
||||
|
||||
val writer = new FileWriter(file)
|
||||
writer.write(contents.toString)
|
||||
writer.close
|
||||
|
||||
return file.toURI.normalize.toUriString
|
||||
}
|
||||
|
||||
override protected getServerModule() {
|
||||
val defaultModule = super.getServerModule()
|
||||
val Module customModule = new AbstractModule() {
|
||||
override protected configure() {
|
||||
bind(WorkspaceManager).in(Scopes.SINGLETON);
|
||||
}
|
||||
}
|
||||
return Modules2.mixin(defaultModule, customModule)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
/**
|
||||
* Copyright (c) 2016, 2020 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.emf.common.util.URI;
|
||||
import org.eclipse.xtext.ide.server.Document;
|
||||
import org.eclipse.xtext.ide.server.ServerModule;
|
||||
import org.eclipse.xtext.ide.server.UriExtensions;
|
||||
import org.eclipse.xtext.ide.server.WorkspaceManager;
|
||||
import org.eclipse.xtext.resource.XtextResource;
|
||||
import org.eclipse.xtext.util.Files;
|
||||
import org.eclipse.xtext.validation.Issue;
|
||||
import org.eclipse.xtext.xbase.lib.IterableExtensions;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
/**
|
||||
* @author Sven Efftinge - Initial contribution and API
|
||||
*/
|
||||
public class WorkspaceManagerTest {
|
||||
@Test
|
||||
public void testDoRead() throws IOException {
|
||||
String model =
|
||||
"type Test {\n" +
|
||||
" string foo\n" +
|
||||
"}\n";
|
||||
URI path = operator_mappedTo("MyType1.testlang", model);
|
||||
workspaceManger.doBuild(Lists.newArrayList(path),
|
||||
Collections.emptyList(), null);
|
||||
String inMemContents =
|
||||
"type Test {\n" +
|
||||
" Test foo\n" +
|
||||
"}\n";
|
||||
workspaceManger.didOpen(path, 1, inMemContents).build(null);
|
||||
Assert.assertEquals(inMemContents,
|
||||
workspaceManger.doRead(path, (Document $0, XtextResource $1) -> $0.getContents()));
|
||||
}
|
||||
|
||||
@Inject
|
||||
protected WorkspaceManager workspaceManger;
|
||||
|
||||
@Inject
|
||||
protected UriExtensions uriExtensions;
|
||||
|
||||
@Before
|
||||
public void setup() throws FileNotFoundException {
|
||||
Injector injector = Guice.createInjector(new ServerModule());
|
||||
injector.injectMembers(this);
|
||||
root = new File("./test-data/test-project");
|
||||
if (!root.mkdirs()) {
|
||||
Files.cleanFolder(root, null, true, false);
|
||||
}
|
||||
root.deleteOnExit();
|
||||
workspaceManger.initialize(uriExtensions.withEmptyAuthority(URI.createFileURI(root.getAbsolutePath())),
|
||||
(URI $0, Iterable<Issue> $1) -> diagnostics.put($0, IterableExtensions.toList($1)), null);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanup() throws FileNotFoundException {
|
||||
if (root.exists()) {
|
||||
Files.cleanFolder(root, null, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
protected Map<URI, List<Issue>> diagnostics = new HashMap<>();
|
||||
|
||||
protected File root;
|
||||
|
||||
public URI operator_mappedTo(String path, CharSequence contents) throws IOException {
|
||||
File file = new File(root, path);
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
try(FileWriter fileWriter = new FileWriter(file)) {
|
||||
fileWriter.write(contents.toString());
|
||||
}
|
||||
return URI.createFileURI(file.getAbsolutePath());
|
||||
}
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016, 2017 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.tests.server
|
||||
|
||||
import com.google.inject.Guice
|
||||
import com.google.inject.Inject
|
||||
import java.io.File
|
||||
import java.io.FileWriter
|
||||
import java.util.List
|
||||
import java.util.Map
|
||||
import org.eclipse.emf.common.util.URI
|
||||
import org.eclipse.xtext.ide.server.ServerModule
|
||||
import org.eclipse.xtext.ide.server.UriExtensions
|
||||
import org.eclipse.xtext.ide.server.WorkspaceManager
|
||||
import org.eclipse.xtext.util.Files
|
||||
import org.eclipse.xtext.validation.Issue
|
||||
import org.junit.After
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* @author Sven Efftinge - Initial contribution and API
|
||||
*/
|
||||
class WorkspaceManagerTest {
|
||||
|
||||
@Test def void testDoRead() {
|
||||
val path = 'MyType1.testlang' -> '''
|
||||
type Test {
|
||||
string foo
|
||||
}
|
||||
'''
|
||||
|
||||
workspaceManger.doBuild(#[path], emptyList, null)
|
||||
|
||||
val String inMemContents = '''
|
||||
type Test {
|
||||
Test foo
|
||||
}
|
||||
'''
|
||||
|
||||
workspaceManger.didOpen(path, 1, inMemContents).build(null)
|
||||
|
||||
Assert.assertEquals(inMemContents, workspaceManger.doRead(path, [$0.contents]))
|
||||
}
|
||||
|
||||
@Inject protected WorkspaceManager workspaceManger
|
||||
@Inject extension protected UriExtensions uriExtensions
|
||||
|
||||
@Before
|
||||
def void setup() {
|
||||
val injector = Guice.createInjector(new ServerModule())
|
||||
injector.injectMembers(this)
|
||||
// register notification callbacks
|
||||
// create workingdir
|
||||
root = new File("./test-data/test-project")
|
||||
if (!root.mkdirs) {
|
||||
Files.cleanFolder(root, null, true, false)
|
||||
}
|
||||
root.deleteOnExit
|
||||
workspaceManger.initialize(URI.createFileURI(root.absolutePath).withEmptyAuthority, [diagnostics.put($0, $1.toList)], null)
|
||||
}
|
||||
|
||||
@After
|
||||
def void cleanup() {
|
||||
if (root.exists) {
|
||||
Files.cleanFolder(root, null, true, true)
|
||||
}
|
||||
}
|
||||
|
||||
protected Map<URI, List<Issue>> diagnostics = newHashMap()
|
||||
protected File root
|
||||
|
||||
def URI ->(String path, CharSequence contents) {
|
||||
val file = new File(root, path)
|
||||
file.parentFile.mkdirs
|
||||
file.createNewFile
|
||||
new FileWriter(file) => [
|
||||
write(contents.toString)
|
||||
close
|
||||
]
|
||||
return URI.createFileURI(file.absolutePath)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
/**
|
||||
* Copyright (c) 2018, 2020 TypeFox and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.testlanguage.editor.syntaxcoloring;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.EStructuralFeature;
|
||||
import org.eclipse.xtext.ide.editor.syntaxcoloring.DefaultSemanticHighlightingCalculator;
|
||||
import org.eclipse.xtext.ide.editor.syntaxcoloring.IHighlightedPositionAcceptor;
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.testLanguage.Operation;
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.testLanguage.Parameter;
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.testLanguage.PrimitiveType;
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.testLanguage.Property;
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.testLanguage.TestLanguagePackage;
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.testLanguage.TypeDeclaration;
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.testLanguage.TypeReference;
|
||||
import org.eclipse.xtext.nodemodel.ICompositeNode;
|
||||
import org.eclipse.xtext.nodemodel.ILeafNode;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
|
||||
import org.eclipse.xtext.util.CancelIndicator;
|
||||
import org.eclipse.xtext.xbase.lib.IterableExtensions;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
public class SemanticHighlightingCalculatorImpl extends DefaultSemanticHighlightingCalculator {
|
||||
private static final String IDENTIFIER_STYLE = "identifier";
|
||||
|
||||
private static final String PRIMITIVE_TYPE_STYLE = "primitiveType";
|
||||
|
||||
private static final String TYPE_STYLE = "type";
|
||||
|
||||
private static final String TYPE_DECLARATION_STYLE = "typeDeclaration";
|
||||
|
||||
private static final String PARAMETER_NAME_STYLE = "parameterName";
|
||||
|
||||
private static final String OP_BODY_STYLE = "opBody";
|
||||
|
||||
public static final Set<String> STYLES = Sets.newHashSet(IDENTIFIER_STYLE, PRIMITIVE_TYPE_STYLE, TYPE_STYLE,
|
||||
TYPE_DECLARATION_STYLE, PARAMETER_NAME_STYLE, OP_BODY_STYLE);
|
||||
|
||||
@Override
|
||||
protected boolean highlightElement(EObject object, IHighlightedPositionAcceptor acceptor,
|
||||
CancelIndicator cancelIndicator) {
|
||||
if (object instanceof Operation) {
|
||||
return doHighlightOperation((Operation) object, acceptor);
|
||||
} else if (object instanceof PrimitiveType) {
|
||||
return doHighlightPrimitiveType((PrimitiveType) object, acceptor);
|
||||
} else if (object instanceof Property) {
|
||||
return doHighlightProperty((Property) object, acceptor);
|
||||
} else if (object instanceof TypeDeclaration) {
|
||||
return doHighlightTypeDeclaration((TypeDeclaration) object, acceptor);
|
||||
} else if (object instanceof TypeReference) {
|
||||
return doHighlightTypeReference((TypeReference) object, acceptor);
|
||||
} else if (object instanceof Parameter) {
|
||||
return doHighlightParameter((Parameter) object, acceptor);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean doHighlightProperty(Property it, IHighlightedPositionAcceptor acceptor) {
|
||||
return doHighlightNode(acceptor, it, TestLanguagePackage.Literals.MEMBER__NAME, IDENTIFIER_STYLE);
|
||||
}
|
||||
|
||||
protected boolean doHighlightOperation(Operation it, IHighlightedPositionAcceptor acceptor) {
|
||||
boolean canStop = doHighlightNode(acceptor, it, TestLanguagePackage.Literals.MEMBER__NAME, IDENTIFIER_STYLE);
|
||||
ICompositeNode opNode = NodeModelUtils.findActualNodeFor(it);
|
||||
if (opNode != null) {
|
||||
List<ILeafNode> inverseChildren = Lists.reverse(
|
||||
Lists.newArrayList(Iterables.filter(opNode.getLeafNodes(), (ILeafNode n) -> !n.isHidden())));
|
||||
int endOffset = -1;
|
||||
int startOffset = -1;
|
||||
ILeafNode first = Iterables.getFirst(inverseChildren, null);
|
||||
String text = null;
|
||||
if (first != null) {
|
||||
text = first.getText();
|
||||
}
|
||||
if ("}".equals(text)) {
|
||||
endOffset = first.getEndOffset() - 1;
|
||||
}
|
||||
if (endOffset != -1) {
|
||||
ILeafNode opStartNode = IterableExtensions.findFirst(inverseChildren,
|
||||
c -> "{".equals(c.getText().trim()));
|
||||
if (opStartNode != null) {
|
||||
startOffset = opStartNode.getOffset() + 1;
|
||||
}
|
||||
}
|
||||
if (startOffset >= 0 && endOffset >= 0) {
|
||||
acceptor.addPosition(startOffset, endOffset - startOffset, OP_BODY_STYLE);
|
||||
}
|
||||
}
|
||||
return canStop;
|
||||
}
|
||||
|
||||
protected boolean doHighlightTypeDeclaration(TypeDeclaration it, IHighlightedPositionAcceptor acceptor) {
|
||||
return doHighlightNode(acceptor, it, TestLanguagePackage.Literals.ABSTRACT_ELEMENT__NAME,
|
||||
TYPE_DECLARATION_STYLE);
|
||||
}
|
||||
|
||||
protected boolean doHighlightPrimitiveType(PrimitiveType it, IHighlightedPositionAcceptor acceptor) {
|
||||
return doHighlightNode(acceptor, it, TestLanguagePackage.Literals.PRIMITIVE_TYPE__NAME, PRIMITIVE_TYPE_STYLE);
|
||||
}
|
||||
|
||||
protected boolean doHighlightTypeReference(TypeReference it, IHighlightedPositionAcceptor acceptor) {
|
||||
return doHighlightNode(acceptor, it, TestLanguagePackage.Literals.TYPE_REFERENCE__TYPE_REF, TYPE_STYLE);
|
||||
}
|
||||
|
||||
protected boolean doHighlightParameter(Parameter it, IHighlightedPositionAcceptor acceptor) {
|
||||
return doHighlightNode(acceptor, it, TestLanguagePackage.Literals.PARAMETER__NAME, PARAMETER_NAME_STYLE);
|
||||
}
|
||||
|
||||
public boolean doHighlightNode(IHighlightedPositionAcceptor acceptor, EObject object, EStructuralFeature feature,
|
||||
String style) {
|
||||
NodeModelUtils.findNodesForFeature(object, feature).forEach((INode it) -> {
|
||||
acceptor.addPosition(it.getOffset(), it.getLength(), style);
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2018 TypeFox and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.tests.testlanguage.editor.syntaxcoloring
|
||||
|
||||
import org.eclipse.emf.ecore.EObject
|
||||
import org.eclipse.emf.ecore.EStructuralFeature
|
||||
import org.eclipse.xtext.ide.editor.syntaxcoloring.DefaultSemanticHighlightingCalculator
|
||||
import org.eclipse.xtext.ide.editor.syntaxcoloring.IHighlightedPositionAcceptor
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.testLanguage.Operation
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.testLanguage.Parameter
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.testLanguage.PrimitiveType
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.testLanguage.Property
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.testLanguage.TypeDeclaration
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.testLanguage.TypeReference
|
||||
import org.eclipse.xtext.nodemodel.util.NodeModelUtils
|
||||
import org.eclipse.xtext.util.CancelIndicator
|
||||
|
||||
import static org.eclipse.xtext.ide.tests.testlanguage.testLanguage.TestLanguagePackage.Literals.*
|
||||
|
||||
class SemanticHighlightingCalculatorImpl extends DefaultSemanticHighlightingCalculator {
|
||||
|
||||
static val IDENTIFIER_STYLE = 'identifier';
|
||||
static val PRIMITIVE_TYPE_STYLE = 'primitiveType';
|
||||
static val TYPE_STYLE = 'type';
|
||||
static val TYPE_DECLARATION_STYLE = 'typeDeclaration';
|
||||
static val PARAMETER_NAME_STYLE = 'parameterName';
|
||||
static val OP_BODY_STYLE = 'opBody';
|
||||
|
||||
public static val STYLES = #{
|
||||
IDENTIFIER_STYLE,
|
||||
PRIMITIVE_TYPE_STYLE,
|
||||
TYPE_STYLE,
|
||||
TYPE_DECLARATION_STYLE,
|
||||
PARAMETER_NAME_STYLE,
|
||||
OP_BODY_STYLE
|
||||
};
|
||||
|
||||
override protected highlightElement(EObject object, IHighlightedPositionAcceptor acceptor,
|
||||
CancelIndicator cancelIndicator) {
|
||||
|
||||
return object.doHighlightElement(acceptor);
|
||||
}
|
||||
|
||||
def dispatch boolean doHighlightElement(EObject it, IHighlightedPositionAcceptor acceptor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
def dispatch boolean doHighlightElement(Property it, IHighlightedPositionAcceptor acceptor) {
|
||||
return acceptor.doHighlightNode(it, MEMBER__NAME, IDENTIFIER_STYLE);
|
||||
}
|
||||
|
||||
def dispatch boolean doHighlightElement(Operation it, IHighlightedPositionAcceptor acceptor) {
|
||||
val canStop = acceptor.doHighlightNode(it, MEMBER__NAME, IDENTIFIER_STYLE);
|
||||
// Besides highlighting the name of the operation, we highlight the body between the braces (exclusive)
|
||||
// to ensure, we can map a single multi-line range into several corresponding highlighting tokens.
|
||||
val opNode = NodeModelUtils.findActualNodeFor(it)
|
||||
if (opNode !== null) {
|
||||
val inverseChildren = opNode.leafNodes.filter[!hidden].toList.reverse;
|
||||
var endOffset = -1;
|
||||
var startOffset = -1;
|
||||
if (inverseChildren.head?.text == '}') {
|
||||
endOffset = inverseChildren.head.endOffset - 1; // exclusive
|
||||
}
|
||||
if (endOffset !== -1) {
|
||||
val opStartNode = inverseChildren.findFirst[text.trim == '{'];
|
||||
if (opStartNode !== null) {
|
||||
startOffset = opStartNode.offset + 1; // exclusive
|
||||
}
|
||||
}
|
||||
if (startOffset >= 0 && endOffset >= 0) {
|
||||
acceptor.addPosition(startOffset, endOffset - startOffset, OP_BODY_STYLE);
|
||||
}
|
||||
}
|
||||
return canStop;
|
||||
}
|
||||
|
||||
def dispatch boolean doHighlightElement(TypeDeclaration it, IHighlightedPositionAcceptor acceptor) {
|
||||
return acceptor.doHighlightNode(it, ABSTRACT_ELEMENT__NAME, TYPE_DECLARATION_STYLE);
|
||||
}
|
||||
|
||||
def dispatch boolean doHighlightElement(PrimitiveType it, IHighlightedPositionAcceptor acceptor) {
|
||||
return acceptor.doHighlightNode(it, PRIMITIVE_TYPE__NAME, PRIMITIVE_TYPE_STYLE);
|
||||
}
|
||||
|
||||
def dispatch boolean doHighlightElement(TypeReference it, IHighlightedPositionAcceptor acceptor) {
|
||||
return acceptor.doHighlightNode(it, TYPE_REFERENCE__TYPE_REF, TYPE_STYLE);
|
||||
}
|
||||
|
||||
def dispatch boolean doHighlightElement(Parameter it, IHighlightedPositionAcceptor acceptor) {
|
||||
return acceptor.doHighlightNode(it, PARAMETER__NAME, PARAMETER_NAME_STYLE);
|
||||
}
|
||||
|
||||
def doHighlightNode(IHighlightedPositionAcceptor acceptor, EObject object, EStructuralFeature feature,
|
||||
String style) {
|
||||
|
||||
NodeModelUtils.findNodesForFeature(object, feature).forEach [
|
||||
acceptor.addPosition(offset, length, style)
|
||||
];
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import java.util.List;
|
||||
import org.eclipse.lsp4j.CodeLens;
|
||||
import org.eclipse.lsp4j.Position;
|
||||
import org.eclipse.xtend2.lib.StringConcatenation;
|
||||
import org.eclipse.xtext.ide.tests.server.AbstractTestLangLanguageServerTest;
|
||||
import org.eclipse.xtext.testing.AbstractLanguageServerTest;
|
||||
import org.eclipse.xtext.xbase.lib.IterableExtensions;
|
||||
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Sven Efftinge - Initial contribution and API
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class CodeLensTest extends AbstractTestLangLanguageServerTest {
|
||||
@Test
|
||||
public void testCodeLens() {
|
||||
final Procedure1<AbstractLanguageServerTest.TestCodeLensConfiguration> _function = (AbstractLanguageServerTest.TestCodeLensConfiguration it) -> {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Foo {}");
|
||||
_builder.newLine();
|
||||
_builder.append("type Bar {");
|
||||
_builder.newLine();
|
||||
_builder.append("\t");
|
||||
_builder.append("Foo foo");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
it.setModel(_builder.toString());
|
||||
final Procedure1<List<? extends CodeLens>> _function_1 = (List<? extends CodeLens> it_1) -> {
|
||||
this.assertEquals("Do Awesome Stuff(RESOLVED)", IterableExtensions.head(it_1).getCommand().getTitle());
|
||||
Object _data = IterableExtensions.head(it_1).getData();
|
||||
Assert.assertEquals(1, ((Position) _data).getLine());
|
||||
};
|
||||
it.setAssertCodeLenses(_function_1);
|
||||
};
|
||||
this.testCodeLens(_function);
|
||||
}
|
||||
}
|
|
@ -1,143 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2018 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
import org.eclipse.lsp4j.ClientCapabilities;
|
||||
import org.eclipse.lsp4j.ExecuteCommandCapabilities;
|
||||
import org.eclipse.lsp4j.ExecuteCommandParams;
|
||||
import org.eclipse.lsp4j.InitializeParams;
|
||||
import org.eclipse.lsp4j.WorkspaceClientCapabilities;
|
||||
import org.eclipse.xtend.lib.annotations.Accessors;
|
||||
import org.eclipse.xtext.ide.tests.server.AbstractTestLangLanguageServerTest;
|
||||
import org.eclipse.xtext.xbase.lib.Exceptions;
|
||||
import org.eclipse.xtext.xbase.lib.Extension;
|
||||
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
|
||||
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
|
||||
import org.eclipse.xtext.xbase.lib.Pure;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Christian Dietrich - Initial contribution and API
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class CommandServiceTest extends AbstractTestLangLanguageServerTest {
|
||||
@Accessors
|
||||
public static class TestExecuteCommandConfiguration {
|
||||
private String command = "";
|
||||
|
||||
private List<Object> args = new ArrayList<Object>();
|
||||
|
||||
private Consumer<Object> assertCommandResult = null;
|
||||
|
||||
@Pure
|
||||
public String getCommand() {
|
||||
return this.command;
|
||||
}
|
||||
|
||||
public void setCommand(final String command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
@Pure
|
||||
public List<Object> getArgs() {
|
||||
return this.args;
|
||||
}
|
||||
|
||||
public void setArgs(final List<Object> args) {
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
@Pure
|
||||
public Consumer<Object> getAssertCommandResult() {
|
||||
return this.assertCommandResult;
|
||||
}
|
||||
|
||||
public void setAssertCommandResult(final Consumer<Object> assertCommandResult) {
|
||||
this.assertCommandResult = assertCommandResult;
|
||||
}
|
||||
}
|
||||
|
||||
protected void testExecuteCommand(final Procedure1<? super CommandServiceTest.TestExecuteCommandConfiguration> configurator) {
|
||||
try {
|
||||
@Extension
|
||||
final CommandServiceTest.TestExecuteCommandConfiguration configuration = new CommandServiceTest.TestExecuteCommandConfiguration();
|
||||
configurator.apply(configuration);
|
||||
final String command = configuration.command;
|
||||
final List<Object> args = configuration.args;
|
||||
ExecuteCommandParams _executeCommandParams = new ExecuteCommandParams(command, args);
|
||||
final CompletableFuture<Object> result = this.languageServer.executeCommand(_executeCommandParams);
|
||||
if ((configuration.assertCommandResult != null)) {
|
||||
final Object value = result.get();
|
||||
configuration.assertCommandResult.accept(value);
|
||||
}
|
||||
} catch (Throwable _e) {
|
||||
throw Exceptions.sneakyThrow(_e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecute() {
|
||||
final Procedure1<InitializeParams> _function = (InitializeParams it) -> {
|
||||
ClientCapabilities _clientCapabilities = new ClientCapabilities();
|
||||
final Procedure1<ClientCapabilities> _function_1 = (ClientCapabilities it_1) -> {
|
||||
WorkspaceClientCapabilities _workspaceClientCapabilities = new WorkspaceClientCapabilities();
|
||||
final Procedure1<WorkspaceClientCapabilities> _function_2 = (WorkspaceClientCapabilities it_2) -> {
|
||||
ExecuteCommandCapabilities _executeCommandCapabilities = new ExecuteCommandCapabilities();
|
||||
final Procedure1<ExecuteCommandCapabilities> _function_3 = (ExecuteCommandCapabilities it_3) -> {
|
||||
it_3.setDynamicRegistration(Boolean.valueOf(true));
|
||||
};
|
||||
ExecuteCommandCapabilities _doubleArrow = ObjectExtensions.<ExecuteCommandCapabilities>operator_doubleArrow(_executeCommandCapabilities, _function_3);
|
||||
it_2.setExecuteCommand(_doubleArrow);
|
||||
};
|
||||
WorkspaceClientCapabilities _doubleArrow = ObjectExtensions.<WorkspaceClientCapabilities>operator_doubleArrow(_workspaceClientCapabilities, _function_2);
|
||||
it_1.setWorkspace(_doubleArrow);
|
||||
};
|
||||
ClientCapabilities _doubleArrow = ObjectExtensions.<ClientCapabilities>operator_doubleArrow(_clientCapabilities, _function_1);
|
||||
it.setCapabilities(_doubleArrow);
|
||||
};
|
||||
this.initialize(_function);
|
||||
final Procedure1<CommandServiceTest.TestExecuteCommandConfiguration> _function_1 = (CommandServiceTest.TestExecuteCommandConfiguration it) -> {
|
||||
it.command = "testlang.a";
|
||||
final Consumer<Object> _function_2 = (Object it_1) -> {
|
||||
if ((it_1 instanceof String)) {
|
||||
this.assertEquals("a", ((String)it_1));
|
||||
} else {
|
||||
Assert.fail("no string");
|
||||
}
|
||||
};
|
||||
it.assertCommandResult = _function_2;
|
||||
};
|
||||
this.testExecuteCommand(_function_1);
|
||||
final Procedure1<CommandServiceTest.TestExecuteCommandConfiguration> _function_2 = (CommandServiceTest.TestExecuteCommandConfiguration it) -> {
|
||||
it.command = "testlang.b";
|
||||
final Consumer<Object> _function_3 = (Object it_1) -> {
|
||||
if ((it_1 instanceof String)) {
|
||||
this.assertEquals("b", ((String)it_1));
|
||||
} else {
|
||||
Assert.fail("no string");
|
||||
}
|
||||
};
|
||||
it.assertCommandResult = _function_3;
|
||||
};
|
||||
this.testExecuteCommand(_function_2);
|
||||
final Procedure1<CommandServiceTest.TestExecuteCommandConfiguration> _function_3 = (CommandServiceTest.TestExecuteCommandConfiguration it) -> {
|
||||
it.command = "doesnotexist.c";
|
||||
final Consumer<Object> _function_4 = (Object it_1) -> {
|
||||
Assert.assertNull(it_1);
|
||||
};
|
||||
it.assertCommandResult = _function_4;
|
||||
};
|
||||
this.testExecuteCommand(_function_3);
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import org.eclipse.xtend2.lib.StringConcatenation;
|
||||
import org.eclipse.xtext.ide.tests.server.AbstractTestLangLanguageServerTest;
|
||||
import org.eclipse.xtext.testing.DefinitionTestConfiguration;
|
||||
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author kosyakov - Initial contribution and API
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class DefinitionTest extends AbstractTestLangLanguageServerTest {
|
||||
@Test
|
||||
public void testDefinition_01() {
|
||||
final Procedure1<DefinitionTestConfiguration> _function = (DefinitionTestConfiguration it) -> {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Foo {}");
|
||||
_builder.newLine();
|
||||
_builder.append("type Bar {");
|
||||
_builder.newLine();
|
||||
_builder.append("\t");
|
||||
_builder.append("Foo foo");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
it.setModel(_builder.toString());
|
||||
it.setLine(2);
|
||||
it.setColumn(3);
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("MyModel.testlang [[0, 5] .. [0, 8]]");
|
||||
_builder_1.newLine();
|
||||
it.setExpectedDefinitions(_builder_1.toString());
|
||||
};
|
||||
this.testDefinition(_function);
|
||||
}
|
||||
}
|
|
@ -1,208 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import org.eclipse.lsp4j.DocumentHighlight;
|
||||
import org.eclipse.lsp4j.DocumentHighlightKind;
|
||||
import org.eclipse.lsp4j.Position;
|
||||
import org.eclipse.xtend2.lib.StringConcatenation;
|
||||
import org.eclipse.xtext.ide.server.occurrences.IDocumentHighlightService;
|
||||
import org.eclipse.xtext.ide.tests.server.AbstractTestLangLanguageServerTest;
|
||||
import org.eclipse.xtext.testing.DocumentHighlightConfiguration;
|
||||
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Class for testing the {@link DocumentHighlightService document highlight
|
||||
* service} behavior through the language server.
|
||||
*
|
||||
* <p>
|
||||
* The string representation of on single {@link DocumentHighlight highlight}
|
||||
* instance is represented with the below pattern:
|
||||
*
|
||||
* <pre>
|
||||
* R|W|T [{d}+, {d}+] .. [{d}+, {d}+]
|
||||
* </pre>
|
||||
*
|
||||
* where the first character describes the {@link DocumentHighlightKind kind} of
|
||||
* the document highlight. If missing, then the value is {@code NaN}. The values
|
||||
* between the first square brackets are the start {@link Position#getLine()
|
||||
* line} and the (zero-based) {@link Position#getCharacter() character offset}
|
||||
* in the line. The second square brackets contains the end position of the
|
||||
* selection and described with the same semantics as the first start range.
|
||||
* Multiple highlight instances are separated by the {@code |} ("pipe")
|
||||
* character.
|
||||
*
|
||||
* @author akos.kitta - Initial contribution and API
|
||||
*
|
||||
* @see DocumentHighlight
|
||||
* @see IDocumentHighlightService
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class DocumentHighlightTest extends AbstractTestLangLanguageServerTest {
|
||||
@Test
|
||||
public void singleLineNoOccurrences_SelectionBeforeWriteSiteMethodName() {
|
||||
final Procedure1<DocumentHighlightConfiguration> _function = (DocumentHighlightConfiguration it) -> {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type A { op foo() { } }");
|
||||
it.setModel(_builder.toString());
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("type A { op");
|
||||
it.setColumn(_builder_1.length());
|
||||
it.setExpectedDocumentHighlight("");
|
||||
};
|
||||
this.testDocumentHighlight(_function);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleLineNoOccurrences_SelectionAfterWriteSiteMethodName() {
|
||||
final Procedure1<DocumentHighlightConfiguration> _function = (DocumentHighlightConfiguration it) -> {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type A { op foo() { } }");
|
||||
it.setModel(_builder.toString());
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("type A { op foo(");
|
||||
it.setColumn(_builder_1.length());
|
||||
it.setExpectedDocumentHighlight("");
|
||||
};
|
||||
this.testDocumentHighlight(_function);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleLineSingleOccurrence() {
|
||||
final Procedure1<DocumentHighlightConfiguration> _function = (DocumentHighlightConfiguration it) -> {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type A { op foo() { } }");
|
||||
it.setModel(_builder.toString());
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("type A { op fo");
|
||||
it.setColumn(_builder_1.length());
|
||||
it.setExpectedDocumentHighlight("W [[0, 12] .. [0, 15]]");
|
||||
};
|
||||
this.testDocumentHighlight(_function);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleLineSingleOccurrenceWithVariable() {
|
||||
final Procedure1<DocumentHighlightConfiguration> _function = (DocumentHighlightConfiguration it) -> {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type A { int foo op foo() { } }");
|
||||
it.setModel(_builder.toString());
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("type A { int fo");
|
||||
it.setColumn(_builder_1.length());
|
||||
it.setExpectedDocumentHighlight("W [[0, 13] .. [0, 16]]");
|
||||
};
|
||||
this.testDocumentHighlight(_function);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleLineSingleOccurrenceWithMultipleTypes() {
|
||||
final Procedure1<DocumentHighlightConfiguration> _function = (DocumentHighlightConfiguration it) -> {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type A { op foo() { } } type B { op foo() { } }");
|
||||
it.setModel(_builder.toString());
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("type A { op fo");
|
||||
it.setColumn(_builder_1.length());
|
||||
it.setExpectedDocumentHighlight("W [[0, 12] .. [0, 15]]");
|
||||
};
|
||||
this.testDocumentHighlight(_function);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleLineMultipleOccurrences_SelectionOnReadSite() {
|
||||
final Procedure1<DocumentHighlightConfiguration> _function = (DocumentHighlightConfiguration it) -> {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type A { op foo() { } op bar() { foo(10) } }");
|
||||
it.setModel(_builder.toString());
|
||||
it.setLine(0);
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("type A { op foo() { } op bar() { fo");
|
||||
it.setColumn(_builder_1.length());
|
||||
it.setExpectedDocumentHighlight("W [[0, 12] .. [0, 15]] | R [[0, 33] .. [0, 36]]");
|
||||
};
|
||||
this.testDocumentHighlight(_function);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleLineMultipleOccurrences_SelectionOnWriteSite() {
|
||||
final Procedure1<DocumentHighlightConfiguration> _function = (DocumentHighlightConfiguration it) -> {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type A { op foo() { } op bar() { foo(10) } }");
|
||||
it.setModel(_builder.toString());
|
||||
it.setLine(0);
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("type A { op fo");
|
||||
it.setColumn(_builder_1.length());
|
||||
it.setExpectedDocumentHighlight("W [[0, 12] .. [0, 15]] | R [[0, 33] .. [0, 36]]");
|
||||
};
|
||||
this.testDocumentHighlight(_function);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleLinesMultipleOccurrences_WithHorizontalTabs() {
|
||||
final Procedure1<DocumentHighlightConfiguration> _function = (DocumentHighlightConfiguration it) -> {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type A {");
|
||||
_builder.newLine();
|
||||
_builder.append("\t");
|
||||
_builder.append("op foo() { }");
|
||||
_builder.newLine();
|
||||
_builder.append("\t");
|
||||
_builder.append("op bar() {");
|
||||
_builder.newLine();
|
||||
_builder.append("\t\t");
|
||||
_builder.append("foo(10)");
|
||||
_builder.newLine();
|
||||
_builder.append("\t");
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
it.setModel(_builder.toString());
|
||||
it.setLine(1);
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("\t");
|
||||
_builder_1.append("op fo");
|
||||
it.setColumn(_builder_1.length());
|
||||
it.setExpectedDocumentHighlight("W [[1, 4] .. [1, 7]] | R [[3, 2] .. [3, 5]]");
|
||||
};
|
||||
this.testDocumentHighlight(_function);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleLinesMultipleOccurrences_WithWhitespaces() {
|
||||
final Procedure1<DocumentHighlightConfiguration> _function = (DocumentHighlightConfiguration it) -> {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type A {");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("op foo() { }");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("op bar() {");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("foo(10)");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
it.setModel(_builder.toString());
|
||||
it.setLine(1);
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append(" ");
|
||||
_builder_1.append("op fo");
|
||||
it.setColumn(_builder_1.length());
|
||||
it.setExpectedDocumentHighlight("W [[1, 7] .. [1, 10]] | R [[3, 8] .. [3, 11]]");
|
||||
};
|
||||
this.testDocumentHighlight(_function);
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2019 Sigasi N.V. (http://www.sigasi.com) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import org.eclipse.xtend2.lib.StringConcatenation;
|
||||
import org.eclipse.xtext.testing.AbstractLanguageServerTest;
|
||||
import org.eclipse.xtext.testing.DocumentHighlightConfiguration;
|
||||
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Class for testing the highlighting of reference that refer to the object in which they are embedded.
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class DocumentHighlightTest2 extends AbstractLanguageServerTest {
|
||||
public DocumentHighlightTest2() {
|
||||
super("nestedRefs");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHighlightDeclarationWithNestedReference() {
|
||||
final Procedure1<DocumentHighlightConfiguration> _function = (DocumentHighlightConfiguration it) -> {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("decl myDecl end myDecl;");
|
||||
_builder.newLine();
|
||||
it.setModel(_builder.toString());
|
||||
it.setLine(0);
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("decl myDec");
|
||||
it.setColumn(_builder_1.length());
|
||||
it.setExpectedDocumentHighlight("W [[0, 5] .. [0, 11]] | R [[0, 16] .. [0, 22]]");
|
||||
};
|
||||
this.testDocumentHighlight(_function);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHighlightNestedReferenceInsideDeclaration() {
|
||||
final Procedure1<DocumentHighlightConfiguration> _function = (DocumentHighlightConfiguration it) -> {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("decl myDecl end myDecl;");
|
||||
_builder.newLine();
|
||||
it.setModel(_builder.toString());
|
||||
it.setLine(0);
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("decl myDecl end myDe");
|
||||
it.setColumn(_builder_1.length());
|
||||
it.setExpectedDocumentHighlight("W [[0, 5] .. [0, 11]] | R [[0, 16] .. [0, 22]]");
|
||||
};
|
||||
this.testDocumentHighlight(_function);
|
||||
}
|
||||
}
|
|
@ -1,166 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2019 NumberFour AG (http://www.enfore.com) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import com.google.inject.Binder;
|
||||
import com.google.inject.binder.AnnotatedBindingBuilder;
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import org.eclipse.emf.common.util.URI;
|
||||
import org.eclipse.lsp4j.DidChangeWatchedFilesParams;
|
||||
import org.eclipse.lsp4j.FileChangeType;
|
||||
import org.eclipse.lsp4j.FileEvent;
|
||||
import org.eclipse.lsp4j.WorkspaceFolder;
|
||||
import org.eclipse.lsp4j.services.WorkspaceService;
|
||||
import org.eclipse.xtend2.lib.StringConcatenation;
|
||||
import org.eclipse.xtext.ide.server.IMultiRootWorkspaceConfigFactory;
|
||||
import org.eclipse.xtext.ide.server.MultiRootWorkspaceConfigFactory;
|
||||
import org.eclipse.xtext.ide.server.ServerModule;
|
||||
import org.eclipse.xtext.ide.tests.server.AbstractTestLangLanguageServerTest;
|
||||
import org.eclipse.xtext.testing.ReferenceTestConfiguration;
|
||||
import org.eclipse.xtext.util.Modules2;
|
||||
import org.eclipse.xtext.workspace.FileProjectConfig;
|
||||
import org.eclipse.xtext.workspace.WorkspaceConfig;
|
||||
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
|
||||
import org.eclipse.xtext.xbase.lib.IterableExtensions;
|
||||
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Checks functionality of method IProjectConfig#isIndexOnly()
|
||||
*
|
||||
* @author Marcus Mews - Initial contribution and API
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class IndexOnlyProjectTest extends AbstractTestLangLanguageServerTest {
|
||||
@Override
|
||||
public com.google.inject.Module getServerModule() {
|
||||
ServerModule _serverModule = new ServerModule();
|
||||
final com.google.inject.Module _function = (Binder it) -> {
|
||||
AnnotatedBindingBuilder<IMultiRootWorkspaceConfigFactory> _bind = it.<IMultiRootWorkspaceConfigFactory>bind(IMultiRootWorkspaceConfigFactory.class);
|
||||
_bind.toInstance(new MultiRootWorkspaceConfigFactory() {
|
||||
@Override
|
||||
public void addProjectsForWorkspaceFolder(final WorkspaceConfig workspaceConfig, final WorkspaceFolder workspaceFolder, final Set<String> existingNames) {
|
||||
String _uri = null;
|
||||
if (workspaceFolder!=null) {
|
||||
_uri=workspaceFolder.getUri();
|
||||
}
|
||||
boolean _tripleNotEquals = (_uri != null);
|
||||
if (_tripleNotEquals) {
|
||||
URI _uri_1 = this.getUriExtensions().toUri(workspaceFolder.getUri());
|
||||
String _uniqueProjectName = this.getUniqueProjectName(workspaceFolder.getName(), existingNames);
|
||||
final FileProjectConfig project = new FileProjectConfig(_uri_1, _uniqueProjectName) {
|
||||
@Override
|
||||
public boolean isIndexOnly() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
project.addSourceFolder(".");
|
||||
workspaceConfig.addProject(project);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
return Modules2.mixin(_serverModule, _function);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows that the resource is indexed
|
||||
*/
|
||||
@Test
|
||||
public void testIndexByUsingReferences() {
|
||||
final Procedure1<ReferenceTestConfiguration> _function = (ReferenceTestConfiguration it) -> {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Foo {}");
|
||||
_builder.newLine();
|
||||
_builder.append("type Bar {");
|
||||
_builder.newLine();
|
||||
_builder.append("\t");
|
||||
_builder.append("Foo foo");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
it.setModel(_builder.toString());
|
||||
it.setColumn("type F".length());
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("MyModel.testlang [[2, 1] .. [2, 4]]");
|
||||
_builder_1.newLine();
|
||||
it.setExpectedReferences(_builder_1.toString());
|
||||
};
|
||||
this.testReferences(_function);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows that the resource is not validated during initial build
|
||||
*/
|
||||
@Test
|
||||
public void testInitializeBuildNoValidation() {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Test {");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("NonExisting foo");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
this.writeFile("MyType1.testlang", _builder);
|
||||
this.initialize();
|
||||
Assert.assertTrue(IterableExtensions.join(this.getDiagnostics().entrySet(), ","), this.getDiagnostics().isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows that the error-free resource is not generated during initial build
|
||||
*/
|
||||
@Test
|
||||
public void testInitializeBuildNoGeneration() {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type TestType {");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("int foo");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
this.writeFile("MyType1.testlang", _builder);
|
||||
this.initialize();
|
||||
final File outputFile = new File(this.root, "src-gen/TestType.java");
|
||||
Assert.assertFalse(IterableExtensions.join(this.getDiagnostics().entrySet(), ","), outputFile.isFile());
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows that the resource is not validated during incremental build
|
||||
*/
|
||||
@Test
|
||||
public void testIncrementalBuildNoValidation() {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Test {");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("NonExisting foo");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
this.writeFile("MyType1.testlang", _builder);
|
||||
this.initialize();
|
||||
Assert.assertTrue(IterableExtensions.join(this.getDiagnostics().entrySet(), ","), this.getDiagnostics().isEmpty());
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("type NonExisting {");
|
||||
_builder_1.newLine();
|
||||
_builder_1.append("}");
|
||||
_builder_1.newLine();
|
||||
final String path = this.writeFile("MyType2.testlang", _builder_1);
|
||||
WorkspaceService _workspaceService = this.languageServer.getWorkspaceService();
|
||||
FileEvent _fileEvent = new FileEvent(path, FileChangeType.Created);
|
||||
DidChangeWatchedFilesParams _didChangeWatchedFilesParams = new DidChangeWatchedFilesParams(Collections.<FileEvent>unmodifiableList(CollectionLiterals.<FileEvent>newArrayList(_fileEvent)));
|
||||
_workspaceService.didChangeWatchedFiles(_didChangeWatchedFilesParams);
|
||||
Assert.assertTrue(IterableExtensions.join(this.getDiagnostics().entrySet(), ","), this.getDiagnostics().isEmpty());
|
||||
}
|
||||
}
|
|
@ -1,113 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.eclipse.lsp4j.DidOpenTextDocumentParams;
|
||||
import org.eclipse.lsp4j.TextDocumentItem;
|
||||
import org.eclipse.lsp4j.jsonrpc.services.ServiceEndpoints;
|
||||
import org.eclipse.xtend2.lib.StringConcatenation;
|
||||
import org.eclipse.xtext.ide.tests.server.AbstractTestLangLanguageServerTest;
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.ide.TestLangLSPExtension;
|
||||
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
|
||||
import org.eclipse.xtext.xbase.lib.Exceptions;
|
||||
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.ObjectExtensions;
|
||||
import org.eclipse.xtext.xbase.lib.Pair;
|
||||
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author efftinge - Initial contribution and API
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class LspExtensionTest extends AbstractTestLangLanguageServerTest {
|
||||
@Test
|
||||
public void testExtension() {
|
||||
try {
|
||||
final String fileURI = this.writeFile("mydoc.testlang", "");
|
||||
this.initialize();
|
||||
final TestLangLSPExtension ext = ServiceEndpoints.<TestLangLSPExtension>toServiceObject(this.languageServer, TestLangLSPExtension.class);
|
||||
DidOpenTextDocumentParams _didOpenTextDocumentParams = new DidOpenTextDocumentParams();
|
||||
final Procedure1<DidOpenTextDocumentParams> _function = (DidOpenTextDocumentParams it) -> {
|
||||
TextDocumentItem _textDocumentItem = new TextDocumentItem();
|
||||
final Procedure1<TextDocumentItem> _function_1 = (TextDocumentItem it_1) -> {
|
||||
it_1.setUri(fileURI);
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("foo bar");
|
||||
_builder.newLine();
|
||||
_builder.append("baz test");
|
||||
_builder.newLine();
|
||||
_builder.append("\t");
|
||||
_builder.append("bla blubb");
|
||||
_builder.newLine();
|
||||
it_1.setText(_builder.toString());
|
||||
};
|
||||
TextDocumentItem _doubleArrow = ObjectExtensions.<TextDocumentItem>operator_doubleArrow(_textDocumentItem, _function_1);
|
||||
it.setTextDocument(_doubleArrow);
|
||||
};
|
||||
DidOpenTextDocumentParams _doubleArrow = ObjectExtensions.<DidOpenTextDocumentParams>operator_doubleArrow(_didOpenTextDocumentParams, _function);
|
||||
this.languageServer.didOpen(_doubleArrow);
|
||||
TestLangLSPExtension.TextOfLineParam _textOfLineParam = new TestLangLSPExtension.TextOfLineParam();
|
||||
final Procedure1<TestLangLSPExtension.TextOfLineParam> _function_1 = (TestLangLSPExtension.TextOfLineParam it) -> {
|
||||
it.uri = fileURI;
|
||||
it.line = 1;
|
||||
};
|
||||
TestLangLSPExtension.TextOfLineParam _doubleArrow_1 = ObjectExtensions.<TestLangLSPExtension.TextOfLineParam>operator_doubleArrow(_textOfLineParam, _function_1);
|
||||
final TestLangLSPExtension.TextOfLineResult result = ext.getTextOfLine(_doubleArrow_1).get();
|
||||
Assert.assertEquals("baz test", result.text);
|
||||
final Function1<Pair<String, Object>, Object> _function_2 = (Pair<String, Object> it) -> {
|
||||
return it.getValue();
|
||||
};
|
||||
Assert.assertEquals(2, IterableExtensions.size(Iterables.<TestLangLSPExtension.BuildNotification>filter(ListExtensions.<Pair<String, Object>, Object>map(this.notifications, _function_2), TestLangLSPExtension.BuildNotification.class)));
|
||||
} catch (Throwable _e) {
|
||||
throw Exceptions.sneakyThrow(_e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtension_readIndex() {
|
||||
try {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type C {");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("op baz() { }");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
_builder.append("type A {");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("op foo() { }");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
_builder.append("type B {");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("op bar() { }");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
this.writeFile("model.testlang", _builder);
|
||||
this.initialize();
|
||||
final TestLangLSPExtension ext = ServiceEndpoints.<TestLangLSPExtension>toServiceObject(this.languageServer, TestLangLSPExtension.class);
|
||||
final List<String> actual = IterableExtensions.<String>sort(IterableExtensions.<String>toList(ext.getAllOpNames().get()));
|
||||
Assert.assertEquals(Collections.<String>unmodifiableList(CollectionLiterals.<String>newArrayList("bar", "baz", "foo")), actual);
|
||||
} catch (Throwable _e) {
|
||||
throw Exceptions.sneakyThrow(_e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,149 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2016, 2017 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.eclipse.emf.common.util.URI;
|
||||
import org.eclipse.xtend2.lib.StringConcatenation;
|
||||
import org.eclipse.xtext.diagnostics.Diagnostic;
|
||||
import org.eclipse.xtext.ide.server.IMultiRootWorkspaceConfigFactory;
|
||||
import org.eclipse.xtext.ide.server.MultiProjectWorkspaceConfigFactory;
|
||||
import org.eclipse.xtext.ide.server.ServerModule;
|
||||
import org.eclipse.xtext.ide.server.WorkspaceManager;
|
||||
import org.eclipse.xtext.util.CancelIndicator;
|
||||
import org.eclipse.xtext.util.Files;
|
||||
import org.eclipse.xtext.util.Modules2;
|
||||
import org.eclipse.xtext.validation.Issue;
|
||||
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
|
||||
import org.eclipse.xtext.xbase.lib.Exceptions;
|
||||
import org.eclipse.xtext.xbase.lib.IterableExtensions;
|
||||
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
|
||||
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
|
||||
import org.eclipse.xtext.xbase.lib.Procedures.Procedure2;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Jan Koehnlein - Initial contribution and API
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class MultiProjectTest {
|
||||
private File project0;
|
||||
|
||||
private File project1;
|
||||
|
||||
private Map<URI, List<Issue>> diagnostics = CollectionLiterals.<URI, List<Issue>>newHashMap();
|
||||
|
||||
@Inject
|
||||
private WorkspaceManager workspaceManager;
|
||||
|
||||
@Test
|
||||
public void testCrossProjectLink() {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Foo {");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("Bar bar");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
final URI foo = this.createFile(this.project0, "Foo.testlang", _builder);
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("type Bar {");
|
||||
_builder_1.newLine();
|
||||
_builder_1.append("}");
|
||||
_builder_1.newLine();
|
||||
final URI bar = this.createFile(this.project1, "Bar.testlang", _builder_1);
|
||||
this.workspaceManager.doBuild(Collections.<URI>unmodifiableList(CollectionLiterals.<URI>newArrayList(foo, bar)), CollectionLiterals.<URI>emptyList(), CancelIndicator.NullImpl);
|
||||
Assert.assertEquals(2, this.diagnostics.size());
|
||||
Assert.assertEquals(1, this.diagnostics.get(foo).size());
|
||||
Assert.assertEquals(Diagnostic.LINKING_DIAGNOSTIC, IterableExtensions.<Issue>head(this.diagnostics.get(foo)).getCode());
|
||||
Assert.assertTrue(this.diagnostics.get(bar).isEmpty());
|
||||
this.diagnostics.clear();
|
||||
List<String> _dependencies = this.workspaceManager.getProjectManager(this.project0.getName()).getProjectDescription().getDependencies();
|
||||
String _name = this.project1.getName();
|
||||
_dependencies.add(_name);
|
||||
this.workspaceManager.doBuild(Collections.<URI>unmodifiableList(CollectionLiterals.<URI>newArrayList(foo, bar)), CollectionLiterals.<URI>emptyList(), CancelIndicator.NullImpl);
|
||||
Assert.assertEquals(2, this.diagnostics.size());
|
||||
Assert.assertTrue(this.diagnostics.get(foo).isEmpty());
|
||||
Assert.assertTrue(this.diagnostics.get(bar).isEmpty());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
ServerModule _serverModule = new ServerModule();
|
||||
final Injector injector = Guice.createInjector(Modules2.mixin(_serverModule, new AbstractModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
this.<IMultiRootWorkspaceConfigFactory>bind(IMultiRootWorkspaceConfigFactory.class).to(MultiProjectWorkspaceConfigFactory.class);
|
||||
}
|
||||
}));
|
||||
injector.injectMembers(this);
|
||||
final File workspaceRoot = this.getRoot("test-data");
|
||||
File _file = new File(workspaceRoot, "test-project0");
|
||||
this.project0 = _file;
|
||||
File _file_1 = new File(workspaceRoot, "test-project1");
|
||||
this.project1 = _file_1;
|
||||
this.project0.mkdir();
|
||||
this.project1.mkdir();
|
||||
final Procedure2<URI, Iterable<Issue>> _function = (URI $0, Iterable<Issue> $1) -> {
|
||||
this.diagnostics.put($0, IterableExtensions.<Issue>toList($1));
|
||||
};
|
||||
this.workspaceManager.initialize(URI.createFileURI(workspaceRoot.getAbsolutePath()), _function, null);
|
||||
}
|
||||
|
||||
protected File getRoot(final String path) {
|
||||
try {
|
||||
File _xblockexpression = null;
|
||||
{
|
||||
final File root = new File(path);
|
||||
boolean _mkdirs = root.mkdirs();
|
||||
boolean _not = (!_mkdirs);
|
||||
if (_not) {
|
||||
Files.cleanFolder(root, null, true, false);
|
||||
}
|
||||
root.deleteOnExit();
|
||||
_xblockexpression = root;
|
||||
}
|
||||
return _xblockexpression;
|
||||
} catch (Throwable _e) {
|
||||
throw Exceptions.sneakyThrow(_e);
|
||||
}
|
||||
}
|
||||
|
||||
public URI createFile(final File root, final String path, final CharSequence contents) {
|
||||
try {
|
||||
final File file = new File(root, path);
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
FileWriter _fileWriter = new FileWriter(file);
|
||||
final Procedure1<FileWriter> _function = (FileWriter it) -> {
|
||||
try {
|
||||
it.write(contents.toString());
|
||||
it.close();
|
||||
} catch (Throwable _e) {
|
||||
throw Exceptions.sneakyThrow(_e);
|
||||
}
|
||||
};
|
||||
ObjectExtensions.<FileWriter>operator_doubleArrow(_fileWriter, _function);
|
||||
return URI.createFileURI(file.getAbsolutePath());
|
||||
} catch (Throwable _e) {
|
||||
throw Exceptions.sneakyThrow(_e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,173 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2016, 2017 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import java.util.Collections;
|
||||
import org.eclipse.lsp4j.Diagnostic;
|
||||
import org.eclipse.lsp4j.DidChangeTextDocumentParams;
|
||||
import org.eclipse.lsp4j.DidChangeWatchedFilesParams;
|
||||
import org.eclipse.lsp4j.FileChangeType;
|
||||
import org.eclipse.lsp4j.FileEvent;
|
||||
import org.eclipse.lsp4j.Position;
|
||||
import org.eclipse.lsp4j.Range;
|
||||
import org.eclipse.lsp4j.TextDocumentContentChangeEvent;
|
||||
import org.eclipse.lsp4j.VersionedTextDocumentIdentifier;
|
||||
import org.eclipse.lsp4j.services.WorkspaceService;
|
||||
import org.eclipse.xtend2.lib.StringConcatenation;
|
||||
import org.eclipse.xtext.ide.tests.server.AbstractTestLangLanguageServerTest;
|
||||
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
|
||||
import org.eclipse.xtext.xbase.lib.IterableExtensions;
|
||||
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
|
||||
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Sven Efftinge - Initial contribution and API
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class OpenDocumentTest extends AbstractTestLangLanguageServerTest {
|
||||
@Test
|
||||
public void testOpenedDocumentShadowsPersistedFile() {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Test {");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("NonExisting foo");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
final String firstFile = this.writeFile("MyType1.testlang", _builder);
|
||||
this.initialize();
|
||||
this.assertEquals("Couldn\'t resolve reference to TypeDeclaration \'NonExisting\'.", IterableExtensions.<Diagnostic>head(this.getDiagnostics().get(firstFile)).getMessage());
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("type Foo {");
|
||||
_builder_1.newLine();
|
||||
_builder_1.append("}");
|
||||
_builder_1.newLine();
|
||||
final String path = this.writeFile("MyType2.testlang", _builder_1);
|
||||
WorkspaceService _workspaceService = this.languageServer.getWorkspaceService();
|
||||
FileEvent _fileEvent = new FileEvent(path, FileChangeType.Created);
|
||||
DidChangeWatchedFilesParams _didChangeWatchedFilesParams = new DidChangeWatchedFilesParams(
|
||||
Collections.<FileEvent>unmodifiableList(CollectionLiterals.<FileEvent>newArrayList(_fileEvent)));
|
||||
_workspaceService.didChangeWatchedFiles(_didChangeWatchedFilesParams);
|
||||
this.assertEquals("Couldn\'t resolve reference to TypeDeclaration \'NonExisting\'.", IterableExtensions.<Diagnostic>head(this.getDiagnostics().get(firstFile)).getMessage());
|
||||
StringConcatenation _builder_2 = new StringConcatenation();
|
||||
_builder_2.append("type NonExisting {");
|
||||
_builder_2.newLine();
|
||||
_builder_2.append("}");
|
||||
_builder_2.newLine();
|
||||
this.open(path, _builder_2.toString());
|
||||
Assert.assertNull(IterableExtensions.<Diagnostic>head(this.getDiagnostics().get(firstFile)));
|
||||
this.close(path);
|
||||
this.assertEquals("Couldn\'t resolve reference to TypeDeclaration \'NonExisting\'.", IterableExtensions.<Diagnostic>head(this.getDiagnostics().get(firstFile)).getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDidChange() {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Test {");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("NonExisting foo");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
final String firstFile = this.writeFile("MyType1.testlang", _builder);
|
||||
this.initialize();
|
||||
this.assertEquals("Couldn\'t resolve reference to TypeDeclaration \'NonExisting\'.", IterableExtensions.<Diagnostic>head(this.getDiagnostics().get(firstFile)).getMessage());
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("type Test {");
|
||||
_builder_1.newLine();
|
||||
_builder_1.append(" ");
|
||||
_builder_1.append("NonExisting foo");
|
||||
_builder_1.newLine();
|
||||
_builder_1.append("}");
|
||||
_builder_1.newLine();
|
||||
this.open(firstFile, _builder_1.toString());
|
||||
this.assertEquals("Couldn\'t resolve reference to TypeDeclaration \'NonExisting\'.", IterableExtensions.<Diagnostic>head(this.getDiagnostics().get(firstFile)).getMessage());
|
||||
DidChangeTextDocumentParams _didChangeTextDocumentParams = new DidChangeTextDocumentParams();
|
||||
final Procedure1<DidChangeTextDocumentParams> _function = (DidChangeTextDocumentParams it) -> {
|
||||
VersionedTextDocumentIdentifier _versionedTextDocumentIdentifier = new VersionedTextDocumentIdentifier();
|
||||
final Procedure1<VersionedTextDocumentIdentifier> _function_1 = (VersionedTextDocumentIdentifier it_1) -> {
|
||||
it_1.setUri(firstFile);
|
||||
it_1.setVersion(Integer.valueOf(2));
|
||||
};
|
||||
VersionedTextDocumentIdentifier _doubleArrow = ObjectExtensions.<VersionedTextDocumentIdentifier>operator_doubleArrow(_versionedTextDocumentIdentifier, _function_1);
|
||||
it.setTextDocument(_doubleArrow);
|
||||
TextDocumentContentChangeEvent _textDocumentContentChangeEvent = new TextDocumentContentChangeEvent();
|
||||
final Procedure1<TextDocumentContentChangeEvent> _function_2 = (TextDocumentContentChangeEvent it_1) -> {
|
||||
Position _position = new Position(1, 4);
|
||||
Position _position_1 = new Position(1, 15);
|
||||
Range _range = new Range(_position, _position_1);
|
||||
it_1.setRange(_range);
|
||||
it_1.setText("Test");
|
||||
};
|
||||
TextDocumentContentChangeEvent _doubleArrow_1 = ObjectExtensions.<TextDocumentContentChangeEvent>operator_doubleArrow(_textDocumentContentChangeEvent, _function_2);
|
||||
it.setContentChanges(Collections.<TextDocumentContentChangeEvent>unmodifiableList(CollectionLiterals.<TextDocumentContentChangeEvent>newArrayList(_doubleArrow_1)));
|
||||
};
|
||||
DidChangeTextDocumentParams _doubleArrow = ObjectExtensions.<DidChangeTextDocumentParams>operator_doubleArrow(_didChangeTextDocumentParams, _function);
|
||||
this.languageServer.didChange(_doubleArrow);
|
||||
Assert.assertNull(IterableExtensions.<Diagnostic>head(this.getDiagnostics().get(firstFile)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDidClose() {
|
||||
final String fileURI = this.writeFile("Foo.testlang", "");
|
||||
this.initialize();
|
||||
final String referencingFileURI = this.getVirtualFile("Bar.testlang");
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Bar {");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("Foo foo");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
this.open(referencingFileURI, _builder.toString());
|
||||
Assert.assertFalse(this.getDiagnostics().get(referencingFileURI).isEmpty());
|
||||
this.open(fileURI, "type Foo {}");
|
||||
Assert.assertTrue(this.getDiagnostics().get(referencingFileURI).isEmpty());
|
||||
this.close(fileURI);
|
||||
Assert.assertFalse(this.getDiagnostics().get(referencingFileURI).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDidCloseInMemory() {
|
||||
this.initialize();
|
||||
final String fileURI = this.getVirtualFile("Foo.testlang");
|
||||
this.open(fileURI, "type Foo {}");
|
||||
final String referencingFileURI = this.getVirtualFile("Bar.testlang");
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Bar {");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("Foo foo");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
this.open(referencingFileURI, _builder.toString());
|
||||
Assert.assertTrue(this.getDiagnostics().get(referencingFileURI).isEmpty());
|
||||
this.close(fileURI);
|
||||
Assert.assertFalse(this.getDiagnostics().get(referencingFileURI).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInMemory_GH_456() {
|
||||
this.initialize();
|
||||
final String uri = "inmemory:/foo/bar.testlang";
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Foo { }");
|
||||
_builder.newLine();
|
||||
this.open(uri, _builder.toString());
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("Diagnostics could be empty but never null.");
|
||||
Assert.assertNotNull(_builder_1.toString(), this.getDiagnostics().get(uri));
|
||||
}
|
||||
}
|
|
@ -1,103 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import java.util.Collections;
|
||||
import org.eclipse.xtend2.lib.StringConcatenation;
|
||||
import org.eclipse.xtext.ide.tests.server.AbstractTestLangLanguageServerTest;
|
||||
import org.eclipse.xtext.testing.ReferenceTestConfiguration;
|
||||
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
|
||||
import org.eclipse.xtext.xbase.lib.Pair;
|
||||
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author kosyakov - Initial contribution and API
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class ReferenceTest extends AbstractTestLangLanguageServerTest {
|
||||
@Test
|
||||
public void testReferences_01() {
|
||||
final Procedure1<ReferenceTestConfiguration> _function = (ReferenceTestConfiguration it) -> {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Foo {}");
|
||||
_builder.newLine();
|
||||
_builder.append("type Bar {");
|
||||
_builder.newLine();
|
||||
_builder.append("\t");
|
||||
_builder.append("Foo foo");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
it.setModel(_builder.toString());
|
||||
it.setColumn("type F".length());
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("MyModel.testlang [[2, 1] .. [2, 4]]");
|
||||
_builder_1.newLine();
|
||||
it.setExpectedReferences(_builder_1.toString());
|
||||
};
|
||||
this.testReferences(_function);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReferences_02() {
|
||||
final Procedure1<ReferenceTestConfiguration> _function = (ReferenceTestConfiguration it) -> {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Foo {}");
|
||||
_builder.newLine();
|
||||
_builder.append("type Bar {");
|
||||
_builder.newLine();
|
||||
_builder.append("\t");
|
||||
_builder.append("Foo foo");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
it.setModel(_builder.toString());
|
||||
it.setColumn("type F".length());
|
||||
it.setIncludeDeclaration(true);
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("MyModel.testlang [[0, 5] .. [0, 8]]");
|
||||
_builder_1.newLine();
|
||||
_builder_1.append("MyModel.testlang [[2, 1] .. [2, 4]]");
|
||||
_builder_1.newLine();
|
||||
it.setExpectedReferences(_builder_1.toString());
|
||||
};
|
||||
this.testReferences(_function);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReferences_03_acrossFiles() {
|
||||
final Procedure1<ReferenceTestConfiguration> _function = (ReferenceTestConfiguration it) -> {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Foo {}");
|
||||
_builder.newLine();
|
||||
Pair<String, String> _mappedTo = Pair.<String, String>of("foo.testlang", _builder.toString());
|
||||
it.setFilesInScope(Collections.<String, CharSequence>unmodifiableMap(CollectionLiterals.<String, CharSequence>newHashMap(_mappedTo)));
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("type Bar {");
|
||||
_builder_1.newLine();
|
||||
_builder_1.append(" ");
|
||||
_builder_1.append("Foo foo");
|
||||
_builder_1.newLine();
|
||||
_builder_1.append("}");
|
||||
_builder_1.newLine();
|
||||
it.setModel(_builder_1.toString());
|
||||
it.setLine(1);
|
||||
it.setColumn(6);
|
||||
it.setIncludeDeclaration(true);
|
||||
StringConcatenation _builder_2 = new StringConcatenation();
|
||||
_builder_2.append("foo.testlang [[0, 5] .. [0, 8]]");
|
||||
_builder_2.newLine();
|
||||
_builder_2.append("MyModel.testlang [[1, 4] .. [1, 7]]");
|
||||
_builder_2.newLine();
|
||||
it.setExpectedReferences(_builder_2.toString());
|
||||
};
|
||||
this.testReferences(_function);
|
||||
}
|
||||
}
|
|
@ -1,203 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2016, 2017 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import org.eclipse.lsp4j.DefinitionParams;
|
||||
import org.eclipse.lsp4j.Diagnostic;
|
||||
import org.eclipse.lsp4j.DidChangeWatchedFilesParams;
|
||||
import org.eclipse.lsp4j.FileChangeType;
|
||||
import org.eclipse.lsp4j.FileEvent;
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
import org.eclipse.lsp4j.jsonrpc.ResponseErrorException;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.ResponseErrorCode;
|
||||
import org.eclipse.lsp4j.services.WorkspaceService;
|
||||
import org.eclipse.xtend2.lib.StringConcatenation;
|
||||
import org.eclipse.xtext.ide.tests.server.AbstractTestLangLanguageServerTest;
|
||||
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
|
||||
import org.eclipse.xtext.xbase.lib.Exceptions;
|
||||
import org.eclipse.xtext.xbase.lib.Functions.Function1;
|
||||
import org.eclipse.xtext.xbase.lib.IterableExtensions;
|
||||
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
|
||||
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Sven Efftinge - Initial contribution and API
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class ServerTest extends AbstractTestLangLanguageServerTest {
|
||||
@Test
|
||||
public void testInitializeBuild() {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Test {");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("string foo");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
this.writeFile("MyType1.testlang", _builder);
|
||||
this.initialize();
|
||||
Assert.assertTrue(IterableExtensions.join(this.getDiagnostics().entrySet(), ","), IterableExtensions.<List<Diagnostic>>head(this.getDiagnostics().values()).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitializeBuildWithError() {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Test {");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("NonExisting foo");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
this.writeFile("MyType1.testlang", _builder);
|
||||
this.initialize();
|
||||
Diagnostic _head = IterableExtensions.<Diagnostic>head(IterableExtensions.<List<Diagnostic>>head(this.getDiagnostics().values()));
|
||||
String _message = null;
|
||||
if (_head!=null) {
|
||||
_message=_head.getMessage();
|
||||
}
|
||||
this.assertEquals("Couldn\'t resolve reference to TypeDeclaration \'NonExisting\'.", _message);
|
||||
Assert.assertEquals(1, IterableExtensions.<Diagnostic>head(IterableExtensions.<List<Diagnostic>>head(this.getDiagnostics().values())).getRange().getStart().getLine());
|
||||
Assert.assertEquals(4, IterableExtensions.<Diagnostic>head(IterableExtensions.<List<Diagnostic>>head(this.getDiagnostics().values())).getRange().getStart().getCharacter());
|
||||
Assert.assertEquals(1, IterableExtensions.<Diagnostic>head(IterableExtensions.<List<Diagnostic>>head(this.getDiagnostics().values())).getRange().getEnd().getLine());
|
||||
Assert.assertEquals(15, IterableExtensions.<Diagnostic>head(IterableExtensions.<List<Diagnostic>>head(this.getDiagnostics().values())).getRange().getEnd().getCharacter());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPublishDiagnosticsAfterInitialized() {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Test {");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("NonExisting foo");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
this.writeFile("MyType1.testlang", _builder);
|
||||
this.initialize(null, false);
|
||||
Assert.assertTrue("Diagnostics produced before \'initialized\' was called", this.getDiagnostics().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncrementalBuildWithError() {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Test {");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("NonExisting foo");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
this.writeFile("MyType1.testlang", _builder);
|
||||
this.initialize();
|
||||
this.assertEquals("Couldn\'t resolve reference to TypeDeclaration \'NonExisting\'.", IterableExtensions.<Diagnostic>head(IterableExtensions.<List<Diagnostic>>head(this.getDiagnostics().values())).getMessage());
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("type NonExisting {");
|
||||
_builder_1.newLine();
|
||||
_builder_1.append("}");
|
||||
_builder_1.newLine();
|
||||
final String path = this.writeFile("MyType2.testlang", _builder_1);
|
||||
WorkspaceService _workspaceService = this.languageServer.getWorkspaceService();
|
||||
FileEvent _fileEvent = new FileEvent(path, FileChangeType.Created);
|
||||
DidChangeWatchedFilesParams _didChangeWatchedFilesParams = new DidChangeWatchedFilesParams(Collections.<FileEvent>unmodifiableList(CollectionLiterals.<FileEvent>newArrayList(_fileEvent)));
|
||||
_workspaceService.didChangeWatchedFiles(_didChangeWatchedFilesParams);
|
||||
Assert.assertNotNull(this.getDiagnostics().get(path));
|
||||
final Function1<List<Diagnostic>, Boolean> _function = (List<Diagnostic> it) -> {
|
||||
return Boolean.valueOf(it.isEmpty());
|
||||
};
|
||||
Assert.assertTrue(IterableExtensions.join(this.getDiagnostics().values(), ","), IterableExtensions.<List<Diagnostic>>forall(this.getDiagnostics().values(), _function));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncrementalDeletion() {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Test {");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("NonExisting foo");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
final String path = this.writeFile("MyType1.testlang", _builder);
|
||||
this.initialize();
|
||||
this.assertEquals("Couldn\'t resolve reference to TypeDeclaration \'NonExisting\'.",
|
||||
IterableExtensions.<Diagnostic>head(IterableExtensions.<List<Diagnostic>>head(this.getDiagnostics().values())).getMessage());
|
||||
this.deleteFile("MyType1.testlang");
|
||||
WorkspaceService _workspaceService = this.languageServer.getWorkspaceService();
|
||||
FileEvent _fileEvent = new FileEvent(path, FileChangeType.Deleted);
|
||||
DidChangeWatchedFilesParams _didChangeWatchedFilesParams = new DidChangeWatchedFilesParams(Collections.<FileEvent>unmodifiableList(CollectionLiterals.<FileEvent>newArrayList(_fileEvent)));
|
||||
_workspaceService.didChangeWatchedFiles(_didChangeWatchedFilesParams);
|
||||
Assert.assertTrue(IterableExtensions.<List<Diagnostic>>head(this.getDiagnostics().values()).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTwoFilesDeleteClose() {
|
||||
final String fileURI = this.writeFile("Foo.testlang", "");
|
||||
this.initialize();
|
||||
final String referencingFileURI = this.getVirtualFile("Bar.testlang");
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Bar {");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("Foo foo");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
this.open(referencingFileURI, _builder.toString());
|
||||
Assert.assertFalse("Bar.testlang references missing type Foo from Foo.testlang: expect error",
|
||||
this.getDiagnostics().get(referencingFileURI).isEmpty());
|
||||
this.open(fileURI, "type Foo {}");
|
||||
Assert.assertTrue("Bar.testlang references type Foo from Foo.testlang: expect no error",
|
||||
this.getDiagnostics().get(referencingFileURI).isEmpty());
|
||||
this.deleteFile(fileURI);
|
||||
WorkspaceService _workspaceService = this.languageServer.getWorkspaceService();
|
||||
FileEvent _fileEvent = new FileEvent(fileURI, FileChangeType.Deleted);
|
||||
DidChangeWatchedFilesParams _didChangeWatchedFilesParams = new DidChangeWatchedFilesParams(Collections.<FileEvent>unmodifiableList(CollectionLiterals.<FileEvent>newArrayList(_fileEvent)));
|
||||
_workspaceService.didChangeWatchedFiles(_didChangeWatchedFilesParams);
|
||||
Assert.assertTrue("delete file on disk: expect no error", this.getDiagnostics().get(referencingFileURI).isEmpty());
|
||||
this.close(fileURI);
|
||||
Assert.assertFalse("close deleted file: expect error", this.getDiagnostics().get(referencingFileURI).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingInitialize() {
|
||||
try {
|
||||
try {
|
||||
DefinitionParams _definitionParams = new DefinitionParams();
|
||||
final Procedure1<DefinitionParams> _function = (DefinitionParams it) -> {
|
||||
TextDocumentIdentifier _textDocumentIdentifier = new TextDocumentIdentifier();
|
||||
final Procedure1<TextDocumentIdentifier> _function_1 = (TextDocumentIdentifier it_1) -> {
|
||||
it_1.setUri("file:/home/test/workspace/mydoc.testlang");
|
||||
};
|
||||
TextDocumentIdentifier _doubleArrow = ObjectExtensions.<TextDocumentIdentifier>operator_doubleArrow(_textDocumentIdentifier, _function_1);
|
||||
it.setTextDocument(_doubleArrow);
|
||||
};
|
||||
DefinitionParams _doubleArrow = ObjectExtensions.<DefinitionParams>operator_doubleArrow(_definitionParams, _function);
|
||||
this.languageServer.definition(_doubleArrow).get();
|
||||
Assert.fail("Expected a ResponseErrorException");
|
||||
} catch (final Throwable _t) {
|
||||
if (_t instanceof ExecutionException) {
|
||||
final ExecutionException exception = (ExecutionException)_t;
|
||||
Throwable _cause = exception.getCause();
|
||||
Assert.assertEquals(ResponseErrorCode.serverNotInitialized.getValue(), ((ResponseErrorException) _cause).getResponseError().getCode());
|
||||
} else {
|
||||
throw Exceptions.sneakyThrow(_t);
|
||||
}
|
||||
}
|
||||
} catch (Throwable _e) {
|
||||
throw Exceptions.sneakyThrow(_e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,171 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2020 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Scopes;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import org.eclipse.lsp4j.DidChangeWorkspaceFoldersParams;
|
||||
import org.eclipse.lsp4j.InitializeParams;
|
||||
import org.eclipse.lsp4j.WorkspaceFolder;
|
||||
import org.eclipse.lsp4j.WorkspaceFoldersChangeEvent;
|
||||
import org.eclipse.xtend2.lib.StringConcatenation;
|
||||
import org.eclipse.xtext.ide.server.ILanguageServerAccess;
|
||||
import org.eclipse.xtext.ide.server.UriExtensions;
|
||||
import org.eclipse.xtext.ide.server.WorkspaceManager;
|
||||
import org.eclipse.xtext.ide.tests.server.AbstractTestLangLanguageServerTest;
|
||||
import org.eclipse.xtext.resource.IResourceDescription;
|
||||
import org.eclipse.xtext.util.Modules2;
|
||||
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
|
||||
import org.eclipse.xtext.xbase.lib.Exceptions;
|
||||
import org.eclipse.xtext.xbase.lib.Extension;
|
||||
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
|
||||
import org.eclipse.xtext.xbase.lib.Procedures.Procedure0;
|
||||
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
/**
|
||||
* @author Jan Koehnlein - Initial contribution and API
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class WorkspaceFoldersTest extends AbstractTestLangLanguageServerTest {
|
||||
@Inject
|
||||
@Extension
|
||||
private UriExtensions _uriExtensions;
|
||||
|
||||
@Inject
|
||||
private WorkspaceManager workspaceManager;
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
@Test
|
||||
public void testInitialize() {
|
||||
try {
|
||||
final File rootFolder1 = this.temporaryFolder.newFolder("root1");
|
||||
final File rootFolder2 = this.temporaryFolder.newFolder("root2");
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Foo {");
|
||||
_builder.newLine();
|
||||
_builder.append("\t");
|
||||
_builder.append("Bar bar");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
this.writeFile(rootFolder1, "one.testlang", _builder);
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("type Bar {");
|
||||
_builder_1.newLine();
|
||||
_builder_1.append("\t");
|
||||
_builder_1.append("Foo foo");
|
||||
_builder_1.newLine();
|
||||
_builder_1.append("}");
|
||||
_builder_1.newLine();
|
||||
final String twoUri = this.writeFile(rootFolder2, "two.testlang", _builder_1);
|
||||
final Procedure1<InitializeParams> _function = (InitializeParams it) -> {
|
||||
String _uriString = this._uriExtensions.toUriString(rootFolder1.toURI());
|
||||
WorkspaceFolder _workspaceFolder = new WorkspaceFolder(_uriString, "root1");
|
||||
String _uriString_1 = this._uriExtensions.toUriString(rootFolder2.toURI());
|
||||
WorkspaceFolder _workspaceFolder_1 = new WorkspaceFolder(_uriString_1, "root2");
|
||||
it.setWorkspaceFolders(Collections.<WorkspaceFolder>unmodifiableList(CollectionLiterals.<WorkspaceFolder>newArrayList(_workspaceFolder, _workspaceFolder_1)));
|
||||
};
|
||||
this.initialize(_function);
|
||||
Assert.assertEquals(2, this.getDiagnostics().size());
|
||||
Assert.assertEquals(1, this.getDiagnostics().get(twoUri).size());
|
||||
final Procedure0 _function_1 = () -> {
|
||||
DidChangeWorkspaceFoldersParams _didChangeWorkspaceFoldersParams = new DidChangeWorkspaceFoldersParams();
|
||||
final Procedure1<DidChangeWorkspaceFoldersParams> _function_2 = (DidChangeWorkspaceFoldersParams it) -> {
|
||||
WorkspaceFoldersChangeEvent _workspaceFoldersChangeEvent = new WorkspaceFoldersChangeEvent();
|
||||
final Procedure1<WorkspaceFoldersChangeEvent> _function_3 = (WorkspaceFoldersChangeEvent it_1) -> {
|
||||
String _uriString = this._uriExtensions.toUriString(rootFolder2.toURI());
|
||||
WorkspaceFolder _workspaceFolder = new WorkspaceFolder(_uriString, "root2");
|
||||
it_1.setRemoved(Collections.<WorkspaceFolder>unmodifiableList(CollectionLiterals.<WorkspaceFolder>newArrayList(_workspaceFolder)));
|
||||
};
|
||||
WorkspaceFoldersChangeEvent _doubleArrow = ObjectExtensions.<WorkspaceFoldersChangeEvent>operator_doubleArrow(_workspaceFoldersChangeEvent, _function_3);
|
||||
it.setEvent(_doubleArrow);
|
||||
};
|
||||
DidChangeWorkspaceFoldersParams _doubleArrow = ObjectExtensions.<DidChangeWorkspaceFoldersParams>operator_doubleArrow(_didChangeWorkspaceFoldersParams, _function_2);
|
||||
this.languageServer.didChangeWorkspaceFolders(_doubleArrow);
|
||||
};
|
||||
this.withBuild(_function_1);
|
||||
Assert.assertEquals(0, this.getDiagnostics().get(twoUri).size());
|
||||
final Procedure0 _function_2 = () -> {
|
||||
DidChangeWorkspaceFoldersParams _didChangeWorkspaceFoldersParams = new DidChangeWorkspaceFoldersParams();
|
||||
final Procedure1<DidChangeWorkspaceFoldersParams> _function_3 = (DidChangeWorkspaceFoldersParams it) -> {
|
||||
WorkspaceFoldersChangeEvent _workspaceFoldersChangeEvent = new WorkspaceFoldersChangeEvent();
|
||||
final Procedure1<WorkspaceFoldersChangeEvent> _function_4 = (WorkspaceFoldersChangeEvent it_1) -> {
|
||||
String _uriString = this._uriExtensions.toUriString(rootFolder2.toURI());
|
||||
WorkspaceFolder _workspaceFolder = new WorkspaceFolder(_uriString, "root2");
|
||||
it_1.setAdded(Collections.<WorkspaceFolder>unmodifiableList(CollectionLiterals.<WorkspaceFolder>newArrayList(_workspaceFolder)));
|
||||
};
|
||||
WorkspaceFoldersChangeEvent _doubleArrow = ObjectExtensions.<WorkspaceFoldersChangeEvent>operator_doubleArrow(_workspaceFoldersChangeEvent, _function_4);
|
||||
it.setEvent(_doubleArrow);
|
||||
};
|
||||
DidChangeWorkspaceFoldersParams _doubleArrow = ObjectExtensions.<DidChangeWorkspaceFoldersParams>operator_doubleArrow(_didChangeWorkspaceFoldersParams, _function_3);
|
||||
this.languageServer.didChangeWorkspaceFolders(_doubleArrow);
|
||||
};
|
||||
this.withBuild(_function_2);
|
||||
Assert.assertEquals(1, this.getDiagnostics().get(twoUri).size());
|
||||
} catch (Throwable _e) {
|
||||
throw Exceptions.sneakyThrow(_e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void withBuild(final Procedure0 lambda) {
|
||||
try {
|
||||
final CompletableFuture<Void> future = new CompletableFuture<Void>();
|
||||
final ILanguageServerAccess.IBuildListener _function = new ILanguageServerAccess.IBuildListener() {
|
||||
@Override
|
||||
public void afterBuild(final List<IResourceDescription.Delta> it) {
|
||||
WorkspaceFoldersTest.this.workspaceManager.removeBuildListener(this);
|
||||
future.complete(null);
|
||||
}
|
||||
};
|
||||
this.workspaceManager.addBuildListener(_function);
|
||||
lambda.apply();
|
||||
future.get();
|
||||
} catch (Throwable _e) {
|
||||
throw Exceptions.sneakyThrow(_e);
|
||||
}
|
||||
}
|
||||
|
||||
public String writeFile(final File root, final String path, final CharSequence contents) {
|
||||
try {
|
||||
final File file = new File(root, path);
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
final FileWriter writer = new FileWriter(file);
|
||||
writer.write(contents.toString());
|
||||
writer.close();
|
||||
return this._uriExtensions.toUriString(file.toURI().normalize());
|
||||
} catch (Throwable _e) {
|
||||
throw Exceptions.sneakyThrow(_e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected com.google.inject.Module getServerModule() {
|
||||
final com.google.inject.Module defaultModule = super.getServerModule();
|
||||
final com.google.inject.Module customModule = new AbstractModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
this.<WorkspaceManager>bind(WorkspaceManager.class).in(Scopes.SINGLETON);
|
||||
}
|
||||
};
|
||||
return Modules2.mixin(defaultModule, customModule);
|
||||
}
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2016, 2017 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.server;
|
||||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.eclipse.emf.common.util.URI;
|
||||
import org.eclipse.xtend2.lib.StringConcatenation;
|
||||
import org.eclipse.xtext.ide.server.Document;
|
||||
import org.eclipse.xtext.ide.server.ServerModule;
|
||||
import org.eclipse.xtext.ide.server.UriExtensions;
|
||||
import org.eclipse.xtext.ide.server.WorkspaceManager;
|
||||
import org.eclipse.xtext.resource.XtextResource;
|
||||
import org.eclipse.xtext.util.Files;
|
||||
import org.eclipse.xtext.validation.Issue;
|
||||
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
|
||||
import org.eclipse.xtext.xbase.lib.Exceptions;
|
||||
import org.eclipse.xtext.xbase.lib.Extension;
|
||||
import org.eclipse.xtext.xbase.lib.Functions.Function2;
|
||||
import org.eclipse.xtext.xbase.lib.IterableExtensions;
|
||||
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
|
||||
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
|
||||
import org.eclipse.xtext.xbase.lib.Procedures.Procedure2;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Sven Efftinge - Initial contribution and API
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class WorkspaceManagerTest {
|
||||
@Test
|
||||
public void testDoRead() {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("type Test {");
|
||||
_builder.newLine();
|
||||
_builder.append(" ");
|
||||
_builder.append("string foo");
|
||||
_builder.newLine();
|
||||
_builder.append("}");
|
||||
_builder.newLine();
|
||||
final URI path = this.operator_mappedTo("MyType1.testlang", _builder);
|
||||
this.workspaceManger.doBuild(Collections.<URI>unmodifiableList(CollectionLiterals.<URI>newArrayList(path)), CollectionLiterals.<URI>emptyList(), null);
|
||||
StringConcatenation _builder_1 = new StringConcatenation();
|
||||
_builder_1.append("type Test {");
|
||||
_builder_1.newLine();
|
||||
_builder_1.append(" ");
|
||||
_builder_1.append("Test foo");
|
||||
_builder_1.newLine();
|
||||
_builder_1.append("}");
|
||||
_builder_1.newLine();
|
||||
final String inMemContents = _builder_1.toString();
|
||||
this.workspaceManger.didOpen(path, Integer.valueOf(1), inMemContents).build(null);
|
||||
final Function2<Document, XtextResource, String> _function = (Document $0, XtextResource $1) -> {
|
||||
return $0.getContents();
|
||||
};
|
||||
Assert.assertEquals(inMemContents, this.workspaceManger.<String>doRead(path, _function));
|
||||
}
|
||||
|
||||
@Inject
|
||||
protected WorkspaceManager workspaceManger;
|
||||
|
||||
@Inject
|
||||
@Extension
|
||||
protected UriExtensions uriExtensions;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
try {
|
||||
ServerModule _serverModule = new ServerModule();
|
||||
final Injector injector = Guice.createInjector(_serverModule);
|
||||
injector.injectMembers(this);
|
||||
File _file = new File("./test-data/test-project");
|
||||
this.root = _file;
|
||||
boolean _mkdirs = this.root.mkdirs();
|
||||
boolean _not = (!_mkdirs);
|
||||
if (_not) {
|
||||
Files.cleanFolder(this.root, null, true, false);
|
||||
}
|
||||
this.root.deleteOnExit();
|
||||
final Procedure2<URI, Iterable<Issue>> _function = (URI $0, Iterable<Issue> $1) -> {
|
||||
this.diagnostics.put($0, IterableExtensions.<Issue>toList($1));
|
||||
};
|
||||
this.workspaceManger.initialize(this.uriExtensions.withEmptyAuthority(URI.createFileURI(this.root.getAbsolutePath())), _function, null);
|
||||
} catch (Throwable _e) {
|
||||
throw Exceptions.sneakyThrow(_e);
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanup() {
|
||||
try {
|
||||
boolean _exists = this.root.exists();
|
||||
if (_exists) {
|
||||
Files.cleanFolder(this.root, null, true, true);
|
||||
}
|
||||
} catch (Throwable _e) {
|
||||
throw Exceptions.sneakyThrow(_e);
|
||||
}
|
||||
}
|
||||
|
||||
protected Map<URI, List<Issue>> diagnostics = CollectionLiterals.<URI, List<Issue>>newHashMap();
|
||||
|
||||
protected File root;
|
||||
|
||||
public URI operator_mappedTo(final String path, final CharSequence contents) {
|
||||
try {
|
||||
final File file = new File(this.root, path);
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
FileWriter _fileWriter = new FileWriter(file);
|
||||
final Procedure1<FileWriter> _function = (FileWriter it) -> {
|
||||
try {
|
||||
it.write(contents.toString());
|
||||
it.close();
|
||||
} catch (Throwable _e) {
|
||||
throw Exceptions.sneakyThrow(_e);
|
||||
}
|
||||
};
|
||||
ObjectExtensions.<FileWriter>operator_doubleArrow(_fileWriter, _function);
|
||||
return URI.createFileURI(file.getAbsolutePath());
|
||||
} catch (Throwable _e) {
|
||||
throw Exceptions.sneakyThrow(_e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,152 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2018 TypeFox and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.ide.tests.testlanguage.editor.syntaxcoloring;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.EStructuralFeature;
|
||||
import org.eclipse.xtext.ide.editor.syntaxcoloring.DefaultSemanticHighlightingCalculator;
|
||||
import org.eclipse.xtext.ide.editor.syntaxcoloring.IHighlightedPositionAcceptor;
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.testLanguage.Operation;
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.testLanguage.Parameter;
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.testLanguage.PrimitiveType;
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.testLanguage.Property;
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.testLanguage.TestLanguagePackage;
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.testLanguage.TypeDeclaration;
|
||||
import org.eclipse.xtext.ide.tests.testlanguage.testLanguage.TypeReference;
|
||||
import org.eclipse.xtext.nodemodel.ICompositeNode;
|
||||
import org.eclipse.xtext.nodemodel.ILeafNode;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
|
||||
import org.eclipse.xtext.util.CancelIndicator;
|
||||
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.ListExtensions;
|
||||
|
||||
@SuppressWarnings("all")
|
||||
public class SemanticHighlightingCalculatorImpl extends DefaultSemanticHighlightingCalculator {
|
||||
private static final String IDENTIFIER_STYLE = "identifier";
|
||||
|
||||
private static final String PRIMITIVE_TYPE_STYLE = "primitiveType";
|
||||
|
||||
private static final String TYPE_STYLE = "type";
|
||||
|
||||
private static final String TYPE_DECLARATION_STYLE = "typeDeclaration";
|
||||
|
||||
private static final String PARAMETER_NAME_STYLE = "parameterName";
|
||||
|
||||
private static final String OP_BODY_STYLE = "opBody";
|
||||
|
||||
public static final Set<String> STYLES = Collections.<String>unmodifiableSet(CollectionLiterals.<String>newHashSet(SemanticHighlightingCalculatorImpl.IDENTIFIER_STYLE, SemanticHighlightingCalculatorImpl.PRIMITIVE_TYPE_STYLE, SemanticHighlightingCalculatorImpl.TYPE_STYLE, SemanticHighlightingCalculatorImpl.TYPE_DECLARATION_STYLE, SemanticHighlightingCalculatorImpl.PARAMETER_NAME_STYLE, SemanticHighlightingCalculatorImpl.OP_BODY_STYLE));
|
||||
|
||||
@Override
|
||||
protected boolean highlightElement(final EObject object, final IHighlightedPositionAcceptor acceptor, final CancelIndicator cancelIndicator) {
|
||||
return this.doHighlightElement(object, acceptor);
|
||||
}
|
||||
|
||||
protected boolean _doHighlightElement(final EObject it, final IHighlightedPositionAcceptor acceptor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean _doHighlightElement(final Property it, final IHighlightedPositionAcceptor acceptor) {
|
||||
return this.doHighlightNode(acceptor, it, TestLanguagePackage.Literals.MEMBER__NAME, SemanticHighlightingCalculatorImpl.IDENTIFIER_STYLE);
|
||||
}
|
||||
|
||||
protected boolean _doHighlightElement(final Operation it, final IHighlightedPositionAcceptor acceptor) {
|
||||
final boolean canStop = this.doHighlightNode(acceptor, it, TestLanguagePackage.Literals.MEMBER__NAME, SemanticHighlightingCalculatorImpl.IDENTIFIER_STYLE);
|
||||
final ICompositeNode opNode = NodeModelUtils.findActualNodeFor(it);
|
||||
if ((opNode != null)) {
|
||||
final Function1<ILeafNode, Boolean> _function = (ILeafNode it_1) -> {
|
||||
boolean _isHidden = it_1.isHidden();
|
||||
return Boolean.valueOf((!_isHidden));
|
||||
};
|
||||
final List<ILeafNode> inverseChildren = ListExtensions.<ILeafNode>reverse(IterableExtensions.<ILeafNode>toList(IterableExtensions.<ILeafNode>filter(opNode.getLeafNodes(), _function)));
|
||||
int endOffset = (-1);
|
||||
int startOffset = (-1);
|
||||
ILeafNode _head = IterableExtensions.<ILeafNode>head(inverseChildren);
|
||||
String _text = null;
|
||||
if (_head!=null) {
|
||||
_text=_head.getText();
|
||||
}
|
||||
boolean _equals = Objects.equal(_text, "}");
|
||||
if (_equals) {
|
||||
int _endOffset = IterableExtensions.<ILeafNode>head(inverseChildren).getEndOffset();
|
||||
int _minus = (_endOffset - 1);
|
||||
endOffset = _minus;
|
||||
}
|
||||
if ((endOffset != (-1))) {
|
||||
final Function1<ILeafNode, Boolean> _function_1 = (ILeafNode it_1) -> {
|
||||
String _trim = it_1.getText().trim();
|
||||
return Boolean.valueOf(Objects.equal(_trim, "{"));
|
||||
};
|
||||
final ILeafNode opStartNode = IterableExtensions.<ILeafNode>findFirst(inverseChildren, _function_1);
|
||||
if ((opStartNode != null)) {
|
||||
int _offset = opStartNode.getOffset();
|
||||
int _plus = (_offset + 1);
|
||||
startOffset = _plus;
|
||||
}
|
||||
}
|
||||
if (((startOffset >= 0) && (endOffset >= 0))) {
|
||||
acceptor.addPosition(startOffset, (endOffset - startOffset), SemanticHighlightingCalculatorImpl.OP_BODY_STYLE);
|
||||
}
|
||||
}
|
||||
return canStop;
|
||||
}
|
||||
|
||||
protected boolean _doHighlightElement(final TypeDeclaration it, final IHighlightedPositionAcceptor acceptor) {
|
||||
return this.doHighlightNode(acceptor, it, TestLanguagePackage.Literals.ABSTRACT_ELEMENT__NAME, SemanticHighlightingCalculatorImpl.TYPE_DECLARATION_STYLE);
|
||||
}
|
||||
|
||||
protected boolean _doHighlightElement(final PrimitiveType it, final IHighlightedPositionAcceptor acceptor) {
|
||||
return this.doHighlightNode(acceptor, it, TestLanguagePackage.Literals.PRIMITIVE_TYPE__NAME, SemanticHighlightingCalculatorImpl.PRIMITIVE_TYPE_STYLE);
|
||||
}
|
||||
|
||||
protected boolean _doHighlightElement(final TypeReference it, final IHighlightedPositionAcceptor acceptor) {
|
||||
return this.doHighlightNode(acceptor, it, TestLanguagePackage.Literals.TYPE_REFERENCE__TYPE_REF, SemanticHighlightingCalculatorImpl.TYPE_STYLE);
|
||||
}
|
||||
|
||||
protected boolean _doHighlightElement(final Parameter it, final IHighlightedPositionAcceptor acceptor) {
|
||||
return this.doHighlightNode(acceptor, it, TestLanguagePackage.Literals.PARAMETER__NAME, SemanticHighlightingCalculatorImpl.PARAMETER_NAME_STYLE);
|
||||
}
|
||||
|
||||
public boolean doHighlightNode(final IHighlightedPositionAcceptor acceptor, final EObject object, final EStructuralFeature feature, final String style) {
|
||||
final Consumer<INode> _function = (INode it) -> {
|
||||
acceptor.addPosition(it.getOffset(), it.getLength(), style);
|
||||
};
|
||||
NodeModelUtils.findNodesForFeature(object, feature).forEach(_function);
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean doHighlightElement(final EObject it, final IHighlightedPositionAcceptor acceptor) {
|
||||
if (it instanceof Operation) {
|
||||
return _doHighlightElement((Operation)it, acceptor);
|
||||
} else if (it instanceof PrimitiveType) {
|
||||
return _doHighlightElement((PrimitiveType)it, acceptor);
|
||||
} else if (it instanceof Property) {
|
||||
return _doHighlightElement((Property)it, acceptor);
|
||||
} else if (it instanceof TypeDeclaration) {
|
||||
return _doHighlightElement((TypeDeclaration)it, acceptor);
|
||||
} else if (it instanceof TypeReference) {
|
||||
return _doHighlightElement((TypeReference)it, acceptor);
|
||||
} else if (it instanceof Parameter) {
|
||||
return _doHighlightElement((Parameter)it, acceptor);
|
||||
} else if (it != null) {
|
||||
return _doHighlightElement(it, acceptor);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unhandled parameter types: " +
|
||||
Arrays.<Object>asList(it, acceptor).toString());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* Copyright (c) 2015, 2020 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.xtext;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.xtext.XtextStandaloneSetup;
|
||||
import org.eclipse.xtext.resource.XtextResource;
|
||||
import org.eclipse.xtext.tests.AbstractXtextTests;
|
||||
import org.eclipse.xtext.util.CancelIndicator;
|
||||
import org.eclipse.xtext.validation.CheckMode;
|
||||
import org.eclipse.xtext.validation.Issue;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* @author efftinge - Initial contribution and API
|
||||
*/
|
||||
public class ReducedXtextResourceValidatorTest extends AbstractXtextTests {
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
with(new XtextStandaloneSetup());
|
||||
resourceValidator = get(ReducedXtextResourceValidator.class);
|
||||
}
|
||||
|
||||
private ReducedXtextResourceValidator resourceValidator;
|
||||
|
||||
@Test
|
||||
public void testNoEcoreLinkingErrors() throws Exception {
|
||||
String grammarAsString = "grammar test.Lang with org.eclipse.xtext.common.Terminals\n" +
|
||||
"import 'http://test' as test\n" +
|
||||
"Root returns test::Foo: name=ID;";
|
||||
List<Issue> issues = resourceValidator.validate(getErroneousResource(grammarAsString),
|
||||
CheckMode.NORMAL_AND_FAST, CancelIndicator.NullImpl);
|
||||
Assert.assertEquals(issues.toString(), 0, issues.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyntaxErrors() throws Exception {
|
||||
String grammarAsString = "grammar test.Lang with org.eclipse.xtext.common.Terminals\n" +
|
||||
"import 'http://test' as test\n" +
|
||||
"Root returns test::Foo: name=ID;;";
|
||||
List<Issue> issues = resourceValidator.validate(getErroneousResource(grammarAsString),
|
||||
CheckMode.NORMAL_AND_FAST, CancelIndicator.NullImpl);
|
||||
Assert.assertEquals(issues.toString(), 1, issues.size());
|
||||
Assert.assertTrue(issues.toString(),
|
||||
Iterables.getFirst(issues, null).getMessage().contains("extraneous input ';'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRuleLinkingErrors() throws Exception {
|
||||
String grammarAsString = "grammar test.Lang with org.eclipse.xtext.common.Terminals\n" +
|
||||
"import 'http://test' as test\n" +
|
||||
"Root returns test::Foo : name=IDS;";
|
||||
List<Issue> issues = resourceValidator.validate(getErroneousResource(grammarAsString),
|
||||
CheckMode.NORMAL_AND_FAST, CancelIndicator.NullImpl);
|
||||
Assert.assertEquals(issues.toString(), 1, issues.size());
|
||||
Assert.assertTrue(issues.toString(), Iterables.getFirst(issues, null).getMessage().contains("IDS"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGrammarLinkingErrors() throws Exception {
|
||||
String grammarAsString = "grammar test.Lang with org.eclipse.xtext.common.Trminals\n" +
|
||||
"import 'http://test' as test\n" +
|
||||
"Root returns test::Foo : name='foo';";
|
||||
List<Issue> issues = resourceValidator.validate(getErroneousResource(grammarAsString),
|
||||
CheckMode.NORMAL_AND_FAST, CancelIndicator.NullImpl);
|
||||
Assert.assertEquals(issues.toString(), 1, issues.size());
|
||||
Assert.assertTrue(issues.toString(), Iterables.getFirst(issues, null).getMessage().contains("Trminals"));
|
||||
}
|
||||
|
||||
public XtextResource getErroneousResource(CharSequence seq) throws Exception {
|
||||
return doGetResource(getAsStream(seq.toString()), getTestModelURI());
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2015 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.xtext
|
||||
|
||||
import org.eclipse.xtext.XtextStandaloneSetup
|
||||
import org.eclipse.xtext.tests.AbstractXtextTests
|
||||
import org.eclipse.xtext.util.CancelIndicator
|
||||
import org.eclipse.xtext.validation.CheckMode
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* @author efftinge - Initial contribution and API
|
||||
*/
|
||||
class ReducedXtextResourceValidatorTest extends AbstractXtextTests {
|
||||
override void setUp() throws Exception {
|
||||
super.setUp()
|
||||
with(new XtextStandaloneSetup())
|
||||
this.resourceValidator = get(ReducedXtextResourceValidator)
|
||||
}
|
||||
|
||||
ReducedXtextResourceValidator resourceValidator
|
||||
|
||||
@Test def void testNoEcoreLinkingErrors() {
|
||||
val grammarAsString = '''
|
||||
grammar test.Lang with org.eclipse.xtext.common.Terminals
|
||||
import 'http://test' as test
|
||||
Root returns test::Foo: name=ID;
|
||||
'''
|
||||
val issues = resourceValidator.validate(grammarAsString.erroneousResource, CheckMode.NORMAL_AND_FAST, CancelIndicator.NullImpl)
|
||||
assertEquals(issues.toString, 0, issues.size)
|
||||
}
|
||||
|
||||
@Test def void testSyntaxErrors() {
|
||||
val grammarAsString = '''
|
||||
grammar test.Lang with org.eclipse.xtext.common.Terminals
|
||||
import 'http://test' as test
|
||||
Root returns test::Foo: name=ID;;
|
||||
'''
|
||||
val issues = resourceValidator.validate(grammarAsString.erroneousResource, CheckMode.NORMAL_AND_FAST, CancelIndicator.NullImpl)
|
||||
assertEquals(issues.toString, 1, issues.size)
|
||||
assertTrue(issues.toString, issues.head.message.contains("extraneous input ';'"))
|
||||
}
|
||||
|
||||
@Test def void testRuleLinkingErrors() {
|
||||
val grammarAsString = '''
|
||||
grammar test.Lang with org.eclipse.xtext.common.Terminals
|
||||
import 'http://test' as test
|
||||
Root returns test::Foo : name=IDS;
|
||||
'''
|
||||
val issues = resourceValidator.validate(grammarAsString.erroneousResource, CheckMode.NORMAL_AND_FAST, CancelIndicator.NullImpl)
|
||||
assertEquals(issues.toString, 1, issues.size)
|
||||
assertTrue(issues.toString, issues.head.message.contains("IDS"))
|
||||
}
|
||||
|
||||
@Test def void testGrammarLinkingErrors() {
|
||||
val grammarAsString = '''
|
||||
grammar test.Lang with org.eclipse.xtext.common.Trminals
|
||||
import 'http://test' as test
|
||||
Root returns test::Foo : name='foo';
|
||||
'''
|
||||
val issues = resourceValidator.validate(grammarAsString.erroneousResource, CheckMode.NORMAL_AND_FAST, CancelIndicator.NullImpl)
|
||||
assertEquals(issues.toString, 1, issues.size)
|
||||
assertTrue(issues.toString, issues.head.message.contains("Trminals"))
|
||||
}
|
||||
|
||||
def getErroneousResource(CharSequence seq) {
|
||||
return seq.toString.asStream.doGetResource(testModelURI)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* Copyright (c) 2019, 2020 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.xtext;
|
||||
|
||||
import org.eclipse.xtext.Grammar;
|
||||
import org.eclipse.xtext.XtextPackage;
|
||||
import org.eclipse.xtext.XtextStandaloneSetup;
|
||||
import org.eclipse.xtext.testing.InjectWith;
|
||||
import org.eclipse.xtext.testing.XtextRunner;
|
||||
import org.eclipse.xtext.testing.util.ParseHelper;
|
||||
import org.eclipse.xtext.testing.validation.ValidationTestHelper;
|
||||
import org.eclipse.xtext.tests.AbstractXtextTests;
|
||||
import org.eclipse.xtext.tests.XtextInjectorProvider;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* @author Eva Poell - Initial contribution and API
|
||||
*/
|
||||
@RunWith(XtextRunner.class)
|
||||
@InjectWith(XtextInjectorProvider.class)
|
||||
public class ValidationIssue1034Test extends AbstractXtextTests {
|
||||
@Inject
|
||||
private ParseHelper<Grammar> parseHelper;
|
||||
|
||||
@Inject
|
||||
private ValidationTestHelper validationTestHelper;
|
||||
|
||||
@Before
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
with(XtextStandaloneSetup.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void check_FirstRuleIsNotFragment() throws Exception {
|
||||
String grammarAsString = "grammar com.space.Test with org.eclipse.xtext.common.Terminals\n" +
|
||||
"generate testDSL 'http://space.com/test'\n" +
|
||||
"Model:\n" +
|
||||
" 'type' type=ID;";
|
||||
validationTestHelper.assertNoIssues(parseHelper.parse(grammarAsString));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void check_FirstRuleIsFragment() throws Exception {
|
||||
String grammarAsString = "grammar com.space.Test with org.eclipse.xtext.common.Terminals\n" +
|
||||
"generate testDSL 'http://space.com/test'\n" +
|
||||
"fragment Model:\n" +
|
||||
" 'type' type=ID;";
|
||||
error(grammarAsString);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void check_FirstRuleIsFragmentEmpty() throws Exception {
|
||||
String grammarAsString = "grammar com.space.Test with org.eclipse.xtext.common.Terminals\n" +
|
||||
"generate testDSL 'http://space.com/test'\n" +
|
||||
"fragment Model:\n" +
|
||||
" 'error'\n" +
|
||||
"Greeting:\n" +
|
||||
" 'Hello' name=ID '!';";
|
||||
error(grammarAsString);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void check_FirstRuleIsFragmentParams() throws Exception {
|
||||
String grammarAsString = "grammar foo with org.eclipse.xtext.common.Terminals\n" +
|
||||
"generate mm 'http://bar'\n" +
|
||||
"fragment MyRule<MyParam>:\n" +
|
||||
" <MyParam> name=ID\n" +
|
||||
" | <!MyParam> name=STRING\n" +
|
||||
" | name='name'\n" +
|
||||
";";
|
||||
error(grammarAsString);
|
||||
}
|
||||
|
||||
private void error(CharSequence input) throws Exception {
|
||||
validationTestHelper.assertError(parseHelper.parse(input), XtextPackage.Literals.PARSER_RULE,
|
||||
XtextConfigurableIssueCodes.INVALID_FRAGMENT_AS_FIRST_RULE, "must not be a fragment");
|
||||
}
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2019 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.xtext
|
||||
|
||||
import com.google.inject.Inject
|
||||
import org.eclipse.xtext.Grammar
|
||||
import org.eclipse.xtext.XtextStandaloneSetup
|
||||
import org.eclipse.xtext.testing.InjectWith
|
||||
import org.eclipse.xtext.testing.XtextRunner
|
||||
import org.eclipse.xtext.testing.util.ParseHelper
|
||||
import org.eclipse.xtext.testing.validation.ValidationTestHelper
|
||||
import org.eclipse.xtext.tests.AbstractXtextTests
|
||||
import org.eclipse.xtext.tests.XtextInjectorProvider
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import static org.eclipse.xtext.XtextPackage.Literals.PARSER_RULE
|
||||
import static org.eclipse.xtext.xtext.XtextConfigurableIssueCodes.INVALID_FRAGMENT_AS_FIRST_RULE
|
||||
|
||||
/**
|
||||
* @author Eva Poell - Initial contribution and API
|
||||
*/
|
||||
@RunWith(XtextRunner)
|
||||
@InjectWith(XtextInjectorProvider)
|
||||
class ValidationIssue1034Test extends AbstractXtextTests {
|
||||
|
||||
@Inject extension ParseHelper<Grammar>
|
||||
@Inject extension ValidationTestHelper
|
||||
|
||||
@Before
|
||||
override setUp() throws Exception {
|
||||
super.setUp();
|
||||
with(XtextStandaloneSetup)
|
||||
}
|
||||
|
||||
@Test
|
||||
def void check_FirstRuleIsNotFragment() {
|
||||
'''grammar com.space.Test with org.eclipse.xtext.common.Terminals
|
||||
generate testDSL "http://space.com/test"
|
||||
Model:
|
||||
"type" type=ID;'''.parse.assertNoIssues
|
||||
}
|
||||
|
||||
@Test
|
||||
def void check_FirstRuleIsFragment() {
|
||||
'''grammar com.space.Test with org.eclipse.xtext.common.Terminals
|
||||
generate testDSL "http://space.com/test"
|
||||
fragment Model:
|
||||
"type" type=ID;'''.error
|
||||
}
|
||||
|
||||
@Test
|
||||
def void check_FirstRuleIsFragmentEmpty() {
|
||||
'''grammar com.space.Test with org.eclipse.xtext.common.Terminals
|
||||
generate testDSL "http://space.com/test"
|
||||
fragment Model:
|
||||
"error"
|
||||
Greeting:
|
||||
'Hello' name=ID '!';'''.error
|
||||
}
|
||||
|
||||
@Test
|
||||
def void check_FirstRuleIsFragmentParams() {
|
||||
'''grammar foo with org.eclipse.xtext.common.Terminals
|
||||
generate mm "http://bar"
|
||||
fragment MyRule<MyParam>:
|
||||
<MyParam> name=ID
|
||||
| <!MyParam> name=STRING
|
||||
| name='name'
|
||||
;'''.error
|
||||
}
|
||||
|
||||
private def error(CharSequence input) {
|
||||
input.parse.assertError(PARSER_RULE, INVALID_FRAGMENT_AS_FIRST_RULE, "must not be a fragment")
|
||||
}
|
||||
}
|
|
@ -1,106 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2015 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.xtext;
|
||||
|
||||
import java.util.List;
|
||||
import org.eclipse.xtend2.lib.StringConcatenation;
|
||||
import org.eclipse.xtext.XtextStandaloneSetup;
|
||||
import org.eclipse.xtext.resource.XtextResource;
|
||||
import org.eclipse.xtext.tests.AbstractXtextTests;
|
||||
import org.eclipse.xtext.util.CancelIndicator;
|
||||
import org.eclipse.xtext.validation.CheckMode;
|
||||
import org.eclipse.xtext.validation.Issue;
|
||||
import org.eclipse.xtext.xbase.lib.Exceptions;
|
||||
import org.eclipse.xtext.xbase.lib.IterableExtensions;
|
||||
import org.eclipse.xtext.xtext.ReducedXtextResourceValidator;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author efftinge - Initial contribution and API
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class ReducedXtextResourceValidatorTest extends AbstractXtextTests {
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
XtextStandaloneSetup _xtextStandaloneSetup = new XtextStandaloneSetup();
|
||||
this.with(_xtextStandaloneSetup);
|
||||
this.resourceValidator = this.<ReducedXtextResourceValidator>get(ReducedXtextResourceValidator.class);
|
||||
}
|
||||
|
||||
private ReducedXtextResourceValidator resourceValidator;
|
||||
|
||||
@Test
|
||||
public void testNoEcoreLinkingErrors() {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("grammar test.Lang with org.eclipse.xtext.common.Terminals");
|
||||
_builder.newLine();
|
||||
_builder.append("import \'http://test\' as test");
|
||||
_builder.newLine();
|
||||
_builder.append("Root returns test::Foo: name=ID;");
|
||||
_builder.newLine();
|
||||
final String grammarAsString = _builder.toString();
|
||||
final List<Issue> issues = this.resourceValidator.validate(this.getErroneousResource(grammarAsString), CheckMode.NORMAL_AND_FAST, CancelIndicator.NullImpl);
|
||||
Assert.assertEquals(issues.toString(), 0, issues.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyntaxErrors() {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("grammar test.Lang with org.eclipse.xtext.common.Terminals");
|
||||
_builder.newLine();
|
||||
_builder.append("import \'http://test\' as test");
|
||||
_builder.newLine();
|
||||
_builder.append("Root returns test::Foo: name=ID;;");
|
||||
_builder.newLine();
|
||||
final String grammarAsString = _builder.toString();
|
||||
final List<Issue> issues = this.resourceValidator.validate(this.getErroneousResource(grammarAsString), CheckMode.NORMAL_AND_FAST, CancelIndicator.NullImpl);
|
||||
Assert.assertEquals(issues.toString(), 1, issues.size());
|
||||
Assert.assertTrue(issues.toString(), IterableExtensions.<Issue>head(issues).getMessage().contains("extraneous input \';\'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRuleLinkingErrors() {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("grammar test.Lang with org.eclipse.xtext.common.Terminals");
|
||||
_builder.newLine();
|
||||
_builder.append("import \'http://test\' as test");
|
||||
_builder.newLine();
|
||||
_builder.append("Root returns test::Foo : name=IDS;");
|
||||
_builder.newLine();
|
||||
final String grammarAsString = _builder.toString();
|
||||
final List<Issue> issues = this.resourceValidator.validate(this.getErroneousResource(grammarAsString), CheckMode.NORMAL_AND_FAST, CancelIndicator.NullImpl);
|
||||
Assert.assertEquals(issues.toString(), 1, issues.size());
|
||||
Assert.assertTrue(issues.toString(), IterableExtensions.<Issue>head(issues).getMessage().contains("IDS"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGrammarLinkingErrors() {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("grammar test.Lang with org.eclipse.xtext.common.Trminals");
|
||||
_builder.newLine();
|
||||
_builder.append("import \'http://test\' as test");
|
||||
_builder.newLine();
|
||||
_builder.append("Root returns test::Foo : name=\'foo\';");
|
||||
_builder.newLine();
|
||||
final String grammarAsString = _builder.toString();
|
||||
final List<Issue> issues = this.resourceValidator.validate(this.getErroneousResource(grammarAsString), CheckMode.NORMAL_AND_FAST, CancelIndicator.NullImpl);
|
||||
Assert.assertEquals(issues.toString(), 1, issues.size());
|
||||
Assert.assertTrue(issues.toString(), IterableExtensions.<Issue>head(issues).getMessage().contains("Trminals"));
|
||||
}
|
||||
|
||||
public XtextResource getErroneousResource(final CharSequence seq) {
|
||||
try {
|
||||
return this.doGetResource(this.getAsStream(seq.toString()), this.getTestModelURI());
|
||||
} catch (Throwable _e) {
|
||||
throw Exceptions.sneakyThrow(_e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,141 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2019 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.xtext;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import org.eclipse.xtend2.lib.StringConcatenation;
|
||||
import org.eclipse.xtext.Grammar;
|
||||
import org.eclipse.xtext.XtextPackage;
|
||||
import org.eclipse.xtext.XtextStandaloneSetup;
|
||||
import org.eclipse.xtext.testing.InjectWith;
|
||||
import org.eclipse.xtext.testing.XtextRunner;
|
||||
import org.eclipse.xtext.testing.util.ParseHelper;
|
||||
import org.eclipse.xtext.testing.validation.ValidationTestHelper;
|
||||
import org.eclipse.xtext.tests.AbstractXtextTests;
|
||||
import org.eclipse.xtext.tests.XtextInjectorProvider;
|
||||
import org.eclipse.xtext.xbase.lib.Exceptions;
|
||||
import org.eclipse.xtext.xbase.lib.Extension;
|
||||
import org.eclipse.xtext.xtext.XtextConfigurableIssueCodes;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/**
|
||||
* @author Eva Poell - Initial contribution and API
|
||||
*/
|
||||
@RunWith(XtextRunner.class)
|
||||
@InjectWith(XtextInjectorProvider.class)
|
||||
@SuppressWarnings("all")
|
||||
public class ValidationIssue1034Test extends AbstractXtextTests {
|
||||
@Inject
|
||||
@Extension
|
||||
private ParseHelper<Grammar> _parseHelper;
|
||||
|
||||
@Inject
|
||||
@Extension
|
||||
private ValidationTestHelper _validationTestHelper;
|
||||
|
||||
@Before
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
this.with(XtextStandaloneSetup.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void check_FirstRuleIsNotFragment() {
|
||||
try {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("grammar com.space.Test with org.eclipse.xtext.common.Terminals");
|
||||
_builder.newLine();
|
||||
_builder.append("\t\t");
|
||||
_builder.append("generate testDSL \"http://space.com/test\"");
|
||||
_builder.newLine();
|
||||
_builder.append("\t\t");
|
||||
_builder.append("Model:");
|
||||
_builder.newLine();
|
||||
_builder.append("\t\t\t");
|
||||
_builder.append("\"type\" type=ID;");
|
||||
this._validationTestHelper.assertNoIssues(this._parseHelper.parse(_builder));
|
||||
} catch (Throwable _e) {
|
||||
throw Exceptions.sneakyThrow(_e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void check_FirstRuleIsFragment() {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("grammar com.space.Test with org.eclipse.xtext.common.Terminals");
|
||||
_builder.newLine();
|
||||
_builder.append("\t\t");
|
||||
_builder.append("generate testDSL \"http://space.com/test\"");
|
||||
_builder.newLine();
|
||||
_builder.append("\t\t");
|
||||
_builder.append("fragment Model:");
|
||||
_builder.newLine();
|
||||
_builder.append("\t\t\t");
|
||||
_builder.append("\"type\" type=ID;");
|
||||
this.error(_builder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void check_FirstRuleIsFragmentEmpty() {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("grammar com.space.Test with org.eclipse.xtext.common.Terminals");
|
||||
_builder.newLine();
|
||||
_builder.append("\t\t");
|
||||
_builder.append("generate testDSL \"http://space.com/test\"");
|
||||
_builder.newLine();
|
||||
_builder.append("\t\t");
|
||||
_builder.append("fragment Model:");
|
||||
_builder.newLine();
|
||||
_builder.append("\t\t\t");
|
||||
_builder.append("\"error\"");
|
||||
_builder.newLine();
|
||||
_builder.append("\t\t");
|
||||
_builder.append("Greeting:");
|
||||
_builder.newLine();
|
||||
_builder.append("\t\t\t");
|
||||
_builder.append("\'Hello\' name=ID \'!\';");
|
||||
this.error(_builder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void check_FirstRuleIsFragmentParams() {
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
_builder.append("grammar foo with org.eclipse.xtext.common.Terminals");
|
||||
_builder.newLine();
|
||||
_builder.append("\t\t");
|
||||
_builder.append("generate mm \"http://bar\"");
|
||||
_builder.newLine();
|
||||
_builder.append("\t\t");
|
||||
_builder.append("fragment MyRule<MyParam>:");
|
||||
_builder.newLine();
|
||||
_builder.append("\t\t ");
|
||||
_builder.append("<MyParam> name=ID");
|
||||
_builder.newLine();
|
||||
_builder.append("\t\t ");
|
||||
_builder.append("| <!MyParam> name=STRING");
|
||||
_builder.newLine();
|
||||
_builder.append("\t\t ");
|
||||
_builder.append("| name=\'name\'");
|
||||
_builder.newLine();
|
||||
_builder.append("\t\t");
|
||||
_builder.append(";");
|
||||
this.error(_builder);
|
||||
}
|
||||
|
||||
private void error(final CharSequence input) {
|
||||
try {
|
||||
this._validationTestHelper.assertError(this._parseHelper.parse(input), XtextPackage.Literals.PARSER_RULE, XtextConfigurableIssueCodes.INVALID_FRAGMENT_AS_FIRST_RULE, "must not be a fragment");
|
||||
} catch (Throwable _e) {
|
||||
throw Exceptions.sneakyThrow(_e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,379 @@
|
|||
/**
|
||||
* Copyright (c) 2015, 2020 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.xtext.generator;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.eclipse.emf.common.util.Diagnostic;
|
||||
import org.eclipse.emf.common.util.DiagnosticChain;
|
||||
import org.eclipse.emf.common.util.TreeIterator;
|
||||
import org.eclipse.emf.common.util.URI;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.EReference;
|
||||
import org.eclipse.emf.ecore.EValidator;
|
||||
import org.eclipse.emf.ecore.resource.Resource;
|
||||
import org.eclipse.emf.ecore.resource.ResourceSet;
|
||||
import org.eclipse.emf.ecore.util.EcoreUtil;
|
||||
import org.eclipse.xtext.AbstractMetamodelDeclaration;
|
||||
import org.eclipse.xtext.Grammar;
|
||||
import org.eclipse.xtext.GrammarUtil;
|
||||
import org.eclipse.xtext.ReferencedMetamodel;
|
||||
import org.eclipse.xtext.XtextPackage;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
|
||||
import org.eclipse.xtext.resource.IResourceDescription;
|
||||
import org.eclipse.xtext.resource.IResourceServiceProvider;
|
||||
import org.eclipse.xtext.resource.XtextResource;
|
||||
import org.eclipse.xtext.resource.impl.ResourceDescriptionsData;
|
||||
import org.eclipse.xtext.xtext.RuleNames;
|
||||
import org.eclipse.xtext.xtext.generator.model.GuiceModuleAccess;
|
||||
import org.eclipse.xtext.xtext.generator.model.StandaloneSetupAccess;
|
||||
import org.eclipse.xtext.xtext.generator.model.project.IXtextProjectConfig;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.inject.Binder;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
/**
|
||||
* Configuration for an Xtext language. Use this class if you need to specify
|
||||
* exactly which generator fragments you want to include, or alternatively
|
||||
* {@link StandardLanguage} to work with the standard fragments.
|
||||
*
|
||||
* <p>
|
||||
* The most important property is {@code name}, which should be set to the
|
||||
* language name exactly as specified in the grammar file. If the default
|
||||
* grammar resolution based on the name does not work in your particular
|
||||
* scenario, set the {@code grammarUri} property instead. Furthermore, use
|
||||
* {@code fileExtensions} to specify the file extensions for your language.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Generator fragments can be added with the {@code fragment} property. See
|
||||
* {@link StandardLanguage} for a list of useful fragments.
|
||||
* </p>
|
||||
*
|
||||
* @noextend This class should not be extended by clients.
|
||||
*/
|
||||
public class XtextGeneratorLanguage extends CompositeGeneratorFragment2 implements IXtextGeneratorLanguage {
|
||||
private static final Logger LOG = Logger.getLogger(XtextGeneratorLanguage.class);
|
||||
|
||||
private String grammarUri;
|
||||
|
||||
private String name;
|
||||
|
||||
private Boolean generateXtendStubs;
|
||||
|
||||
private Grammar grammar;
|
||||
|
||||
private RuleNames ruleNames;
|
||||
|
||||
private List<String> fileExtensions;
|
||||
|
||||
private List<String> referencedResources = new ArrayList<>();
|
||||
|
||||
private ResourceSet resourceSet;
|
||||
|
||||
private com.google.inject.Module guiceModule = (Binder it) -> {
|
||||
};
|
||||
|
||||
private final StandaloneSetupAccess runtimeGenSetup = new StandaloneSetupAccess();
|
||||
|
||||
private final GuiceModuleAccess runtimeGenModule = new GuiceModuleAccess();
|
||||
|
||||
private final GuiceModuleAccess ideGenModule = new GuiceModuleAccess();
|
||||
|
||||
private final GuiceModuleAccess eclipsePluginGenModule = new GuiceModuleAccess();
|
||||
|
||||
private final GuiceModuleAccess webGenModule = new GuiceModuleAccess();
|
||||
|
||||
@Inject
|
||||
private Provider<ResourceSet> resourceSetProvider;
|
||||
|
||||
@Inject
|
||||
private IXtextProjectConfig projectConfig;
|
||||
|
||||
@Inject
|
||||
private CodeConfig codeConfig;
|
||||
|
||||
@Inject
|
||||
private XtextGeneratorResourceSetInitializer resourceSetInitializer;
|
||||
|
||||
/**
|
||||
* The URI of the grammar file. Use this property if the automatic grammar
|
||||
* resolution based on {@link #setName(String)} does not work in your
|
||||
* particular scenario.
|
||||
*/
|
||||
public void setGrammarUri(String uri) {
|
||||
this.grammarUri = uri;
|
||||
}
|
||||
|
||||
public String getGrammarUri() {
|
||||
if (grammarUri != null) {
|
||||
return grammarUri;
|
||||
} else {
|
||||
return new File(projectConfig.getRuntime().getSrc().getPath(), name.replace(".", "/") + ".xtext").toURI()
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The language name exactly as specified in the grammar.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Either a single file extension or a comma-separated list of extensions
|
||||
* for which the language shall be registered.
|
||||
*/
|
||||
public void setFileExtensions(String fileExtensions) {
|
||||
this.fileExtensions = Arrays.asList(fileExtensions.trim().split("\\s*,\\s*"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a resource to be included in the resource set that will be used to
|
||||
* load the grammar file. This is often necessary if additional Ecore models
|
||||
* are referenced by the grammar.
|
||||
*/
|
||||
public void addReferencedResource(String referencedResource) {
|
||||
referencedResources.add(referencedResource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getFileExtensions() {
|
||||
if (fileExtensions == null || fileExtensions.isEmpty()) {
|
||||
setFileExtensions(GrammarUtil.getSimpleName(grammar).toLowerCase());
|
||||
LOG.info("No explicit fileExtensions configured. Using '*." + fileExtensions + "'.");
|
||||
}
|
||||
return fileExtensions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link CodeConfig#setPreferXtendStubs(boolean)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public void setGenerateXtendStubs(Boolean generateXtendStubs) {
|
||||
this.generateXtendStubs = generateXtendStubs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link CodeConfig#isPreferXtendStubs()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean isGenerateXtendStubs() {
|
||||
if (generateXtendStubs != null) {
|
||||
return generateXtendStubs.booleanValue();
|
||||
} else {
|
||||
return codeConfig.isPreferXtendStubs();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(Injector injector) {
|
||||
getFragments().addAll(0, getImplicitFragments());
|
||||
injector.injectMembers(this);
|
||||
if (resourceSet == null) {
|
||||
resourceSet = resourceSetProvider.get();
|
||||
}
|
||||
resourceSetInitializer.initialize(resourceSet, referencedResources);
|
||||
if (!resourceSet.getResources().isEmpty()) {
|
||||
installIndex();
|
||||
int i = 0;
|
||||
int size = resourceSet.getResources().size();
|
||||
while (i < size) {
|
||||
Resource res = resourceSet.getResources().get(i);
|
||||
if (res.getContents().isEmpty()) {
|
||||
LOG.error("Error loading '" + res.getURI() + "'");
|
||||
} else {
|
||||
if (!res.getErrors().isEmpty()) {
|
||||
LOG.error("Error loading '" + res.getURI() + "':\n" + Joiner.on("\n").join(res.getErrors()));
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
EcoreUtil.resolveAll(resourceSet);
|
||||
}
|
||||
if (getGrammarUri() == null) {
|
||||
throw new IllegalStateException("No grammarUri or language name given");
|
||||
}
|
||||
XtextResource resource = (XtextResource) resourceSet.getResource(URI.createURI(getGrammarUri()), true);
|
||||
if (resource.getContents().isEmpty()) {
|
||||
throw new IllegalArgumentException("Couldn't load grammar for '" + getGrammarUri() + "'.");
|
||||
}
|
||||
if (!resource.getErrors().isEmpty()) {
|
||||
LOG.error(resource.getErrors());
|
||||
throw new IllegalStateException(
|
||||
"Problem parsing '" + getGrammarUri() + "':\n" + Joiner.on("\n").join(resource.getErrors()));
|
||||
}
|
||||
Grammar grammar = (Grammar) resource.getContents().get(0);
|
||||
validateGrammar(grammar);
|
||||
initialize(grammar);
|
||||
super.initialize(injector);
|
||||
}
|
||||
|
||||
protected List<? extends IXtextGeneratorFragment> getImplicitFragments() {
|
||||
List<ImplicitFragment> fragments = new ArrayList<>();
|
||||
fragments.add(new ImplicitFragment());
|
||||
return fragments;
|
||||
}
|
||||
|
||||
public void initialize(Grammar grammar) {
|
||||
this.grammar = grammar;
|
||||
this.ruleNames = RuleNames.getRuleNames(grammar, true);
|
||||
}
|
||||
|
||||
private void installIndex() {
|
||||
ResourceDescriptionsData index = new ResourceDescriptionsData(Collections.emptyList());
|
||||
List<Resource> resources = Lists.newArrayList(resourceSet.getResources());
|
||||
for (Resource resource : resources) {
|
||||
index(resource, resource.getURI(), index);
|
||||
}
|
||||
ResourceDescriptionsData.ResourceSetAdapter.installResourceDescriptionsData(resourceSet, index);
|
||||
}
|
||||
|
||||
private void index(Resource resource, URI uri, ResourceDescriptionsData index) {
|
||||
IResourceServiceProvider serviceProvider = IResourceServiceProvider.Registry.INSTANCE
|
||||
.getResourceServiceProvider(uri);
|
||||
if (serviceProvider != null) {
|
||||
IResourceDescription resourceDescription = serviceProvider.getResourceDescriptionManager()
|
||||
.getResourceDescription(resource);
|
||||
if (resourceDescription != null) {
|
||||
index.addDescription(uri, resourceDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateGrammar(Grammar grammar) {
|
||||
validateAllImports(grammar);
|
||||
EValidator validator = EValidator.Registry.INSTANCE.getEValidator(XtextPackage.eINSTANCE);
|
||||
if (validator != null) {
|
||||
DiagnosticChain chain = new DiagnosticChain() {
|
||||
@Override
|
||||
public void add(Diagnostic diagnostic) {
|
||||
if (diagnostic.getSeverity() == Diagnostic.ERROR) {
|
||||
String grammarName = "Validation Error in " + grammar.getName() + ": ";
|
||||
if (diagnostic.getException() == null) {
|
||||
throw new IllegalStateException(grammarName + diagnostic.getMessage());
|
||||
} else {
|
||||
throw new IllegalStateException(grammarName + diagnostic.getMessage(),
|
||||
diagnostic.getException());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAll(Diagnostic diagnostic) {
|
||||
add(diagnostic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void merge(Diagnostic diagnostic) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
validator.validate(grammar, chain, null);
|
||||
TreeIterator<EObject> iterator = grammar.eAllContents();
|
||||
while (iterator.hasNext()) {
|
||||
validator.validate(iterator.next(), chain, new HashMap<Object, Object>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateAllImports(Grammar grammar) {
|
||||
for (AbstractMetamodelDeclaration amd : GrammarUtil.allMetamodelDeclarations(grammar)) {
|
||||
if (amd instanceof ReferencedMetamodel) {
|
||||
validateReferencedMetamodel(((ReferencedMetamodel) amd));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateReferencedMetamodel(ReferencedMetamodel ref) {
|
||||
if (ref.getEPackage() != null && !ref.getEPackage().eIsProxy()) {
|
||||
return;
|
||||
}
|
||||
EReference eref = XtextPackage.Literals.ABSTRACT_METAMODEL_DECLARATION__EPACKAGE;
|
||||
List<INode> nodes = NodeModelUtils.findNodesForFeature(ref, eref);
|
||||
String refName = null;
|
||||
if (nodes.isEmpty()) {
|
||||
refName = "(unknown)";
|
||||
} else {
|
||||
refName = NodeModelUtils.getTokenText(nodes.get(0));
|
||||
}
|
||||
String grammarName = GrammarUtil.getGrammar(ref).getName();
|
||||
String msg = "The EPackage " + refName + " in grammar " + grammarName + " could not be found. "
|
||||
+ "You might want to register that EPackage in your workflow file.";
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Grammar getGrammar() {
|
||||
return grammar;
|
||||
}
|
||||
|
||||
public RuleNames getRuleNames() {
|
||||
return ruleNames;
|
||||
}
|
||||
|
||||
public List<String> getReferencedResources() {
|
||||
return referencedResources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceSet getResourceSet() {
|
||||
return resourceSet;
|
||||
}
|
||||
|
||||
public void setResourceSet(ResourceSet resourceSet) {
|
||||
this.resourceSet = resourceSet;
|
||||
}
|
||||
|
||||
public com.google.inject.Module getGuiceModule() {
|
||||
return guiceModule;
|
||||
}
|
||||
|
||||
public void setGuiceModule(com.google.inject.Module guiceModule) {
|
||||
this.guiceModule = guiceModule;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StandaloneSetupAccess getRuntimeGenSetup() {
|
||||
return runtimeGenSetup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuiceModuleAccess getRuntimeGenModule() {
|
||||
return runtimeGenModule;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuiceModuleAccess getIdeGenModule() {
|
||||
return ideGenModule;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuiceModuleAccess getEclipsePluginGenModule() {
|
||||
return eclipsePluginGenModule;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuiceModuleAccess getWebGenModule() {
|
||||
return webGenModule;
|
||||
}
|
||||
}
|
|
@ -1,285 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2015, 2020 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.xtext.generator
|
||||
|
||||
import com.google.common.base.Joiner
|
||||
import com.google.common.collect.Lists
|
||||
import com.google.inject.Inject
|
||||
import com.google.inject.Injector
|
||||
import com.google.inject.Module
|
||||
import com.google.inject.Provider
|
||||
import java.io.File
|
||||
import java.util.Collections
|
||||
import java.util.HashMap
|
||||
import java.util.List
|
||||
import org.apache.log4j.Logger
|
||||
import org.eclipse.emf.common.util.Diagnostic
|
||||
import org.eclipse.emf.common.util.DiagnosticChain
|
||||
import org.eclipse.emf.common.util.URI
|
||||
import org.eclipse.emf.ecore.EValidator
|
||||
import org.eclipse.emf.ecore.resource.Resource
|
||||
import org.eclipse.emf.ecore.resource.ResourceSet
|
||||
import org.eclipse.emf.ecore.util.EcoreUtil
|
||||
import org.eclipse.xtend.lib.annotations.Accessors
|
||||
import org.eclipse.xtext.Grammar
|
||||
import org.eclipse.xtext.GrammarUtil
|
||||
import org.eclipse.xtext.ReferencedMetamodel
|
||||
import org.eclipse.xtext.XtextPackage
|
||||
import org.eclipse.xtext.nodemodel.util.NodeModelUtils
|
||||
import org.eclipse.xtext.resource.IResourceServiceProvider
|
||||
import org.eclipse.xtext.resource.XtextResource
|
||||
import org.eclipse.xtext.resource.impl.ResourceDescriptionsData
|
||||
import org.eclipse.xtext.xtext.RuleNames
|
||||
import org.eclipse.xtext.xtext.generator.model.GuiceModuleAccess
|
||||
import org.eclipse.xtext.xtext.generator.model.StandaloneSetupAccess
|
||||
import org.eclipse.xtext.xtext.generator.model.project.IXtextProjectConfig
|
||||
|
||||
/**
|
||||
* Configuration for an Xtext language. Use this class if you need to specify exactly which generator
|
||||
* fragments you want to include, or alternatively {@link StandardLanguage} to work with the standard
|
||||
* fragments.
|
||||
*
|
||||
* <p>The most important property is {@code name}, which should be set to the language name exactly
|
||||
* as specified in the grammar file. If the default grammar resolution based on the name does not
|
||||
* work in your particular scenario, set the {@code grammarUri} property instead. Furthermore,
|
||||
* use {@code fileExtensions} to specify the file extensions for your language.</p>
|
||||
*
|
||||
* <p>Generator fragments can be added with the {@code fragment} property. See {@link StandardLanguage}
|
||||
* for a list of useful fragments.</p>
|
||||
*
|
||||
* @noextend This class should not be extended by clients.
|
||||
*/
|
||||
class XtextGeneratorLanguage extends CompositeGeneratorFragment2 implements IXtextGeneratorLanguage {
|
||||
|
||||
static val Logger LOG = Logger.getLogger(XtextGeneratorLanguage)
|
||||
|
||||
String grammarUri
|
||||
|
||||
String name
|
||||
|
||||
Boolean generateXtendStubs
|
||||
|
||||
@Accessors(PUBLIC_GETTER)
|
||||
Grammar grammar
|
||||
|
||||
@Accessors(PUBLIC_GETTER)
|
||||
RuleNames ruleNames
|
||||
|
||||
@Accessors(PUBLIC_GETTER)
|
||||
List<String> fileExtensions
|
||||
|
||||
@Accessors(PUBLIC_GETTER)
|
||||
List<String> referencedResources = newArrayList()
|
||||
|
||||
@Accessors
|
||||
ResourceSet resourceSet
|
||||
|
||||
@Accessors
|
||||
Module guiceModule = []
|
||||
|
||||
@Accessors
|
||||
val runtimeGenSetup = new StandaloneSetupAccess
|
||||
|
||||
@Accessors
|
||||
val runtimeGenModule = new GuiceModuleAccess
|
||||
|
||||
@Accessors
|
||||
val ideGenModule = new GuiceModuleAccess
|
||||
|
||||
@Accessors
|
||||
val eclipsePluginGenModule = new GuiceModuleAccess
|
||||
|
||||
@Accessors
|
||||
val webGenModule = new GuiceModuleAccess
|
||||
|
||||
@Inject Provider<ResourceSet> resourceSetProvider
|
||||
|
||||
@Inject IXtextProjectConfig projectConfig
|
||||
|
||||
@Inject CodeConfig codeConfig
|
||||
|
||||
@Inject XtextGeneratorResourceSetInitializer resourceSetInitializer
|
||||
|
||||
/**
|
||||
* The URI of the grammar file. Use this property if the automatic grammar resolution based on {@link #setName(String)}
|
||||
* does not work in your particular scenario.
|
||||
*/
|
||||
def void setGrammarUri(String uri) {
|
||||
this.grammarUri = uri
|
||||
}
|
||||
|
||||
def String getGrammarUri() {
|
||||
grammarUri ?: new File(projectConfig.runtime.src.path, name.replace('.', '/') + ".xtext").toURI.toString
|
||||
}
|
||||
|
||||
/**
|
||||
* The language name exactly as specified in the grammar.
|
||||
*/
|
||||
def void setName(String name) {
|
||||
this.name = name
|
||||
}
|
||||
|
||||
/**
|
||||
* Either a single file extension or a comma-separated list of extensions for which the language
|
||||
* shall be registered.
|
||||
*/
|
||||
def void setFileExtensions(String fileExtensions) {
|
||||
this.fileExtensions = fileExtensions.trim.split('\\s*,\\s*').toList
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a resource to be included in the resource set that will be used to load the grammar file.
|
||||
* This is often necessary if additional Ecore models are referenced by the grammar.
|
||||
*/
|
||||
def void addReferencedResource(String referencedResource) {
|
||||
this.referencedResources += referencedResource
|
||||
}
|
||||
|
||||
override getFileExtensions() {
|
||||
if (fileExtensions === null || fileExtensions.empty) {
|
||||
fileExtensions = GrammarUtil.getSimpleName(grammar).toLowerCase
|
||||
LOG.info("No explicit fileExtensions configured. Using '*." + fileExtensions + "'.")
|
||||
}
|
||||
return fileExtensions
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link CodeConfig#setPreferXtendStubs(boolean)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
def void setGenerateXtendStubs(Boolean generateXtendStubs) {
|
||||
this.generateXtendStubs = generateXtendStubs
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link CodeConfig#isPreferXtendStubs()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
override isGenerateXtendStubs() {
|
||||
if (generateXtendStubs !== null) generateXtendStubs.booleanValue else codeConfig.preferXtendStubs
|
||||
}
|
||||
|
||||
override initialize(Injector injector) {
|
||||
fragments.addAll(0, implicitFragments)
|
||||
injector.injectMembers(this)
|
||||
if (resourceSet === null)
|
||||
resourceSet = resourceSetProvider.get()
|
||||
resourceSetInitializer.initialize(resourceSet, referencedResources)
|
||||
|
||||
if (!resourceSet.resources.isEmpty) {
|
||||
installIndex()
|
||||
for (var i = 0, var size = resourceSet.resources.size; i < size; i++) {
|
||||
val res = resourceSet.resources.get(i)
|
||||
if (res.getContents().isEmpty())
|
||||
XtextGeneratorLanguage.LOG.error("Error loading '" + res.getURI() + "'")
|
||||
else if (!res.getErrors().isEmpty())
|
||||
XtextGeneratorLanguage.LOG.error("Error loading '" + res.getURI() + "':\n" + Joiner.on('\n').join(res.getErrors()))
|
||||
}
|
||||
EcoreUtil.resolveAll(resourceSet)
|
||||
}
|
||||
if (getGrammarUri === null) {
|
||||
throw new IllegalStateException("No grammarUri or language name given")
|
||||
}
|
||||
val resource = resourceSet.getResource(URI.createURI(getGrammarUri), true) as XtextResource
|
||||
if (resource.contents.isEmpty) {
|
||||
throw new IllegalArgumentException("Couldn't load grammar for '" + getGrammarUri + "'.")
|
||||
}
|
||||
if (!resource.errors.isEmpty) {
|
||||
XtextGeneratorLanguage.LOG.error(resource.errors)
|
||||
throw new IllegalStateException("Problem parsing '" + getGrammarUri + "':\n" + Joiner.on('\n').join(resource.getErrors()))
|
||||
}
|
||||
|
||||
val grammar = resource.contents.get(0) as Grammar
|
||||
validateGrammar(grammar)
|
||||
initialize(grammar)
|
||||
super.initialize(injector)
|
||||
}
|
||||
|
||||
protected def List<? extends IXtextGeneratorFragment> getImplicitFragments() {
|
||||
val fragments = newArrayList
|
||||
fragments += new ImplicitFragment
|
||||
return fragments
|
||||
}
|
||||
|
||||
def void initialize(Grammar grammar) {
|
||||
this.grammar = grammar
|
||||
this.ruleNames = RuleNames.getRuleNames(grammar, true)
|
||||
}
|
||||
|
||||
private def void installIndex() {
|
||||
val index = new ResourceDescriptionsData(Collections.emptyList)
|
||||
val resources = Lists.newArrayList(resourceSet.resources)
|
||||
for (resource : resources) {
|
||||
index(resource, resource.URI, index)
|
||||
}
|
||||
ResourceDescriptionsData.ResourceSetAdapter.installResourceDescriptionsData(resourceSet, index)
|
||||
}
|
||||
|
||||
private def void index(Resource resource, URI uri, ResourceDescriptionsData index) {
|
||||
val serviceProvider = IResourceServiceProvider.Registry.INSTANCE.getResourceServiceProvider(uri)
|
||||
if (serviceProvider !== null) {
|
||||
val resourceDescription = serviceProvider.resourceDescriptionManager.getResourceDescription(resource)
|
||||
if (resourceDescription !== null) {
|
||||
index.addDescription(uri, resourceDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected def void validateGrammar(Grammar grammar) {
|
||||
validateAllImports(grammar)
|
||||
val validator = EValidator.Registry.INSTANCE.getEValidator(XtextPackage.eINSTANCE)
|
||||
if (validator !== null) {
|
||||
val chain = new DiagnosticChain() {
|
||||
|
||||
override add(Diagnostic diagnostic) {
|
||||
if (diagnostic.severity == Diagnostic.ERROR) {
|
||||
val grammarName = "Validation Error in " + grammar.name + ": "
|
||||
if (diagnostic.exception === null)
|
||||
throw new IllegalStateException(grammarName + diagnostic.message)
|
||||
else
|
||||
throw new IllegalStateException(grammarName + diagnostic.message, diagnostic.exception)
|
||||
}
|
||||
}
|
||||
|
||||
override addAll(Diagnostic diagnostic) {
|
||||
add(diagnostic)
|
||||
}
|
||||
|
||||
override merge(Diagnostic diagnostic) {
|
||||
throw new UnsupportedOperationException
|
||||
}
|
||||
}
|
||||
validator.validate(grammar, chain, null)
|
||||
val iterator = grammar.eAllContents
|
||||
while (iterator.hasNext) {
|
||||
validator.validate(iterator.next, chain, new HashMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected def void validateAllImports(Grammar grammar) {
|
||||
for (amd : GrammarUtil.allMetamodelDeclarations(grammar)) {
|
||||
if (amd instanceof ReferencedMetamodel)
|
||||
validateReferencedMetamodel(amd)
|
||||
}
|
||||
}
|
||||
|
||||
protected def void validateReferencedMetamodel(ReferencedMetamodel ref) {
|
||||
if (ref.EPackage !== null && !ref.EPackage.eIsProxy) {
|
||||
return
|
||||
}
|
||||
val eref = XtextPackage.Literals.ABSTRACT_METAMODEL_DECLARATION__EPACKAGE
|
||||
val nodes = NodeModelUtils.findNodesForFeature(ref, eref)
|
||||
val refName = if (nodes.empty) '(unknown)' else NodeModelUtils.getTokenText(nodes.get(0))
|
||||
val grammarName = GrammarUtil.getGrammar(ref).name
|
||||
val msg = "The EPackage " + refName + " in grammar " + grammarName + " could not be found. "
|
||||
+ "You might want to register that EPackage in your workflow file."
|
||||
throw new IllegalStateException(msg)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,223 @@
|
|||
/**
|
||||
* Copyright (c) 2015, 2020 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.xtext.generator.model.project;
|
||||
|
||||
import org.eclipse.emf.mwe2.runtime.Mandatory;
|
||||
import org.eclipse.xtext.xtext.generator.Issues;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* Specialized project configuration that uses standard names and paths. Usually
|
||||
* it is sufficient to set the {@code baseName} and {@code rootPath} properties
|
||||
* and to enable the required subprojects.
|
||||
*
|
||||
* @noextend This class should not be extended by clients.
|
||||
*/
|
||||
public class StandardProjectConfig extends XtextProjectConfig {
|
||||
/**
|
||||
* set to {@code true} by the project wizard(s) in case "Maven/Gradle"
|
||||
* source layout is selected.
|
||||
*/
|
||||
private boolean mavenLayout;
|
||||
|
||||
private boolean createEclipseMetaData;
|
||||
|
||||
private String rootPath;
|
||||
|
||||
private String baseName;
|
||||
|
||||
/**
|
||||
* The base name of the project, which is usually equal to the runtime
|
||||
* subproject.
|
||||
*/
|
||||
@Mandatory
|
||||
public String setBaseName(String baseName) {
|
||||
return this.baseName = baseName;
|
||||
}
|
||||
|
||||
/**
|
||||
* The root path, usually {@code ".."}.
|
||||
*/
|
||||
@Mandatory
|
||||
public String setRootPath(String rootPath) {
|
||||
return this.rootPath = rootPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkConfiguration(Issues issues) {
|
||||
super.checkConfiguration(issues);
|
||||
if (rootPath == null) {
|
||||
issues.addError("The property 'rootPath' must be set", this);
|
||||
}
|
||||
if (baseName == null) {
|
||||
issues.addError("The property 'baseName' must be set", this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaults() {
|
||||
super.setDefaults();
|
||||
for(SubProjectConfig it : getEnabledProjects()) {
|
||||
if (it.getName() == null) {
|
||||
it.setName(computeName(it));
|
||||
}
|
||||
if (it.getRootPath() == null) {
|
||||
it.setRoot(computeRoot(it));
|
||||
}
|
||||
if (it.getMetaInfPath() == null) {
|
||||
it.setMetaInf(computeMetaInf(it));
|
||||
}
|
||||
if (it.getSrcPath() == null) {
|
||||
it.setSrc(computeSrc(it));
|
||||
}
|
||||
if (it.getSrcGenPath() == null) {
|
||||
it.setSrcGen(computeSrcGen(it));
|
||||
}
|
||||
if (it.getIconsPath() == null) {
|
||||
it.setIcons(computeIcons(it));
|
||||
}
|
||||
if (it instanceof BundleProjectConfig) {
|
||||
if (createEclipseMetaData) {
|
||||
BundleProjectConfig bundleProjectConfig = (BundleProjectConfig) it;
|
||||
if (bundleProjectConfig.getManifest() == null) {
|
||||
bundleProjectConfig.setManifest(newManifestAccess());
|
||||
}
|
||||
if (bundleProjectConfig.getPluginXml() == null) {
|
||||
bundleProjectConfig.setPluginXml(newPluginXmlAccess());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (it instanceof RuntimeProjectConfig) {
|
||||
RuntimeProjectConfig runtimeProjectConfig = (RuntimeProjectConfig) it;
|
||||
if (!(runtimeProjectConfig.getEcoreModelPath() != null)) {
|
||||
runtimeProjectConfig.setEcoreModel(computeEcoreModel(runtimeProjectConfig));
|
||||
}
|
||||
}
|
||||
if (it instanceof WebProjectConfig) {
|
||||
WebProjectConfig webProjectConfig = (WebProjectConfig) it;
|
||||
if (webProjectConfig.getAssetsPath() == null) {
|
||||
webProjectConfig.setAssets(computeAssets(webProjectConfig));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected String computeName(SubProjectConfig project) {
|
||||
if (Objects.equal(project, getRuntime())) {
|
||||
return baseName;
|
||||
} else if (Objects.equal(project, getRuntimeTest())) {
|
||||
if (!mavenLayout) {
|
||||
return baseName + ".tests";
|
||||
} else {
|
||||
return baseName;
|
||||
}
|
||||
} else if (Objects.equal(project, getGenericIde())) {
|
||||
return baseName + ".ide";
|
||||
} else if (Objects.equal(project, getEclipsePlugin())) {
|
||||
return baseName + ".ui";
|
||||
} else if (Objects.equal(project, getEclipsePluginTest())) {
|
||||
if (!mavenLayout) {
|
||||
return baseName + ".ui.tests";
|
||||
} else {
|
||||
return baseName + ".ui";
|
||||
}
|
||||
} else if (Objects.equal(project, getWeb())) {
|
||||
return baseName + ".web";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String computeRoot(SubProjectConfig project) {
|
||||
return rootPath + "/"+ project.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* In case of "Maven/Gradle" source layout the src outlet is named
|
||||
* 'src/main/java', test classes go into 'src/test/java' instead of any
|
||||
* dedicated '...tests' project.
|
||||
*/
|
||||
protected String computeSrc(SubProjectConfig project) {
|
||||
if (mavenLayout) {
|
||||
return project.getRootPath() + "/" + "src/"+ computeSourceSet(project) + "/java";
|
||||
} else {
|
||||
return project.getRootPath() + "/" + "src";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In case of "Maven/Gradle" source layout the srcGen outlet is named
|
||||
* 'src/main/xtext-gen', test-related srcGen classes go into
|
||||
* 'src/test/xtext-gen' instead of any dedicated '...tests' project. Don't
|
||||
* confuse it with 'src/main/xtend-gen'!
|
||||
*/
|
||||
protected String computeSrcGen(SubProjectConfig project) {
|
||||
if (mavenLayout) {
|
||||
return project.getRootPath() + "/" + "src/"+ computeSourceSet(project) + "/xtext-gen";
|
||||
} else {
|
||||
return project.getRootPath() + "/" + "src-gen";
|
||||
}
|
||||
}
|
||||
|
||||
protected String computeMetaInf(SubProjectConfig project) {
|
||||
if (mavenLayout) {
|
||||
return project.getRootPath() + "/" + "src/"+ computeSourceSet(project) + "/resources/META-INF";
|
||||
} else {
|
||||
return project.getRootPath() + "/" + "META-INF";
|
||||
}
|
||||
}
|
||||
|
||||
protected String computeEcoreModel(RuntimeProjectConfig project) {
|
||||
return project.getRootPath() + "/" + "model/generated";
|
||||
}
|
||||
|
||||
protected String computeAssets(WebProjectConfig project) {
|
||||
if (mavenLayout) {
|
||||
return project.getRootPath() + "/" + "src/"+ computeSourceSet(project) + "/webapp";
|
||||
} else {
|
||||
return project.getRootPath() + "/" + "WebRoot";
|
||||
}
|
||||
}
|
||||
|
||||
protected String computeSourceSet(SubProjectConfig project) {
|
||||
if (getTestProjects().contains(project)) {
|
||||
return "test";
|
||||
} else {
|
||||
return "main";
|
||||
}
|
||||
}
|
||||
|
||||
protected String computeIcons(SubProjectConfig project) {
|
||||
return project.getRootPath() + "/" + "icons";
|
||||
}
|
||||
|
||||
public boolean isMavenLayout() {
|
||||
return mavenLayout;
|
||||
}
|
||||
|
||||
public void setMavenLayout(boolean mavenLayout) {
|
||||
this.mavenLayout = mavenLayout;
|
||||
}
|
||||
|
||||
public boolean isCreateEclipseMetaData() {
|
||||
return createEclipseMetaData;
|
||||
}
|
||||
|
||||
public void setCreateEclipseMetaData(boolean createEclipseMetaData) {
|
||||
this.createEclipseMetaData = createEclipseMetaData;
|
||||
}
|
||||
|
||||
public String getRootPath() {
|
||||
return rootPath;
|
||||
}
|
||||
|
||||
public String getBaseName() {
|
||||
return baseName;
|
||||
}
|
||||
}
|
|
@ -1,141 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2015, 2017 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.xtext.generator.model.project
|
||||
|
||||
import org.eclipse.emf.mwe2.runtime.Mandatory
|
||||
import org.eclipse.xtend.lib.annotations.Accessors
|
||||
import org.eclipse.xtext.xtext.generator.Issues
|
||||
|
||||
/**
|
||||
* Specialized project configuration that uses standard names and paths. Usually it is sufficient to
|
||||
* set the {@code baseName} and {@code rootPath} properties and to enable the required subprojects.
|
||||
*
|
||||
* @noextend This class should not be extended by clients.
|
||||
*/
|
||||
@Accessors
|
||||
class StandardProjectConfig extends XtextProjectConfig {
|
||||
|
||||
/** set to {@code true} by the project wizard(s) in case "Maven/Gradle" source layout is selected. */
|
||||
boolean mavenLayout
|
||||
boolean createEclipseMetaData
|
||||
String rootPath
|
||||
String baseName
|
||||
|
||||
/**
|
||||
* The base name of the project, which is usually equal to the runtime subproject.
|
||||
*/
|
||||
@Mandatory
|
||||
def setBaseName(String baseName) {
|
||||
this.baseName = baseName
|
||||
}
|
||||
|
||||
/**
|
||||
* The root path, usually {@code ".."}.
|
||||
*/
|
||||
@Mandatory
|
||||
def setRootPath(String rootPath) {
|
||||
this.rootPath = rootPath
|
||||
}
|
||||
|
||||
override checkConfiguration(Issues issues) {
|
||||
super.checkConfiguration(issues)
|
||||
if (rootPath === null)
|
||||
issues.addError("The property 'rootPath' must be set", this)
|
||||
if (baseName === null)
|
||||
issues.addError("The property 'baseName' must be set", this)
|
||||
}
|
||||
|
||||
override setDefaults() {
|
||||
super.setDefaults
|
||||
enabledProjects.forEach [
|
||||
if (name === null)
|
||||
name = computeName
|
||||
if (it.rootPath === null)
|
||||
root = computeRoot
|
||||
if (metaInfPath === null)
|
||||
metaInf = computeMetaInf
|
||||
if (srcPath === null)
|
||||
src = computeSrc
|
||||
if (srcGenPath === null)
|
||||
srcGen = computeSrcGen
|
||||
if (iconsPath === null)
|
||||
icons = computeIcons
|
||||
if (it instanceof BundleProjectConfig) {
|
||||
if (createEclipseMetaData) {
|
||||
if (manifest === null)
|
||||
manifest = newManifestAccess
|
||||
if (pluginXml === null)
|
||||
pluginXml = newPluginXmlAccess
|
||||
}
|
||||
}
|
||||
if (it instanceof RuntimeProjectConfig) {
|
||||
if (ecoreModelPath === null)
|
||||
ecoreModel = computeEcoreModel
|
||||
}
|
||||
if (it instanceof WebProjectConfig) {
|
||||
if (assetsPath === null)
|
||||
assets = computeAssets
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
protected def computeName(SubProjectConfig project) {
|
||||
switch project {
|
||||
case runtime: baseName
|
||||
case runtimeTest: if (!mavenLayout) baseName + '.tests' else baseName
|
||||
case genericIde: baseName + '.ide'
|
||||
case eclipsePlugin: baseName + '.ui'
|
||||
case eclipsePluginTest: if (!mavenLayout) baseName + '.ui.tests' else baseName + '.ui'
|
||||
case web: baseName + '.web'
|
||||
}
|
||||
}
|
||||
|
||||
protected def computeRoot(SubProjectConfig project) {
|
||||
rootPath + '/' + project.name
|
||||
}
|
||||
|
||||
/**
|
||||
* In case of "Maven/Gradle" source layout the src outlet is named 'src/main/java',
|
||||
* test classes go into 'src/test/java' instead of any dedicated '...tests' project.
|
||||
*/
|
||||
protected def computeSrc(SubProjectConfig project) {
|
||||
project.rootPath + '/' + if(mavenLayout) 'src/' + project.computeSourceSet + '/java' else 'src'
|
||||
}
|
||||
|
||||
/**
|
||||
* In case of "Maven/Gradle" source layout the srcGen outlet is named 'src/main/xtext-gen',
|
||||
* test-related srcGen classes go into 'src/test/xtext-gen' instead of any dedicated '...tests' project.
|
||||
* Don't confuse it with 'src/main/xtend-gen'!
|
||||
*/
|
||||
protected def computeSrcGen(SubProjectConfig project) {
|
||||
project.rootPath + '/' + if(mavenLayout) 'src/' + project.computeSourceSet + '/xtext-gen' else 'src-gen'
|
||||
}
|
||||
|
||||
protected def computeMetaInf(SubProjectConfig project) {
|
||||
project.rootPath + '/' + if(mavenLayout) 'src/' + project.computeSourceSet + '/resources/META-INF' else 'META-INF'
|
||||
}
|
||||
|
||||
protected def computeEcoreModel(RuntimeProjectConfig project) {
|
||||
project.rootPath + '/' + 'model/generated'
|
||||
}
|
||||
|
||||
protected def computeAssets(WebProjectConfig project) {
|
||||
project.rootPath + '/' + if(mavenLayout) 'src/' + project.computeSourceSet + '/webapp' else 'WebRoot'
|
||||
}
|
||||
|
||||
protected def computeSourceSet(SubProjectConfig project) {
|
||||
if(testProjects.contains(project)) 'test' else 'main'
|
||||
}
|
||||
|
||||
protected def computeIcons(SubProjectConfig project) {
|
||||
project.rootPath + '/' + 'icons'
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,314 @@
|
|||
/**
|
||||
* Copyright (c) 2015, 2020 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.xtext.generator.parser.antlr;
|
||||
|
||||
import java.io.CharArrayWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.xtext.AbstractRule;
|
||||
import org.eclipse.xtext.Grammar;
|
||||
import org.eclipse.xtext.GrammarUtil;
|
||||
import org.eclipse.xtext.ParserRule;
|
||||
import org.eclipse.xtext.UnorderedGroup;
|
||||
import org.eclipse.xtext.generator.LineSeparatorHarmonizer;
|
||||
import org.eclipse.xtext.util.Strings;
|
||||
import org.eclipse.xtext.xtext.generator.AbstractXtextGeneratorFragment;
|
||||
import org.eclipse.xtext.xtext.generator.CodeConfig;
|
||||
import org.eclipse.xtext.xtext.generator.Issues;
|
||||
import org.eclipse.xtext.xtext.generator.model.IXtextGeneratorFileSystemAccess;
|
||||
import org.eclipse.xtext.xtext.generator.model.TypeReference;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.postProcessing.SuppressWarningsProcessor;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.AntlrCodeQualityHelper;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.AntlrLexerSplitter;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.AntlrParserSplitter;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.BacktrackingGuardForUnorderedGroupsRemover;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.BacktrackingGuardRemover;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.PartialClassExtractor;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.SyntacticPredicateFixup;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.UnorderedGroupsSplitter;
|
||||
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
public abstract class AbstractAntlrGeneratorFragment2 extends AbstractXtextGeneratorFragment {
|
||||
@Inject
|
||||
private AntlrToolFacade antlrTool;
|
||||
|
||||
@Inject
|
||||
private AntlrCodeQualityHelper codeQualityHelper;
|
||||
|
||||
@Inject
|
||||
private LineSeparatorHarmonizer newLineNormalizer;
|
||||
|
||||
@Inject
|
||||
private CodeConfig codeConfig;
|
||||
|
||||
private AntlrOptions options = new AntlrOptions();
|
||||
|
||||
private ArrayList<String> antlrParams = new ArrayList<>();
|
||||
|
||||
public void addAntlrParam(String param) {
|
||||
antlrParams.add(param);
|
||||
}
|
||||
|
||||
public String[] getAntlrParams() {
|
||||
ArrayList<String> params = Lists.newArrayList(antlrParams);
|
||||
// setting the default conversion timeout to 100secs.
|
||||
// There seem to be no practical situations where the NFA conversion
|
||||
// would hang,
|
||||
// so Terence suggested here [1] to remove the option all together
|
||||
// [1] -
|
||||
// http://antlr.1301665.n2.nabble.com/Xconversiontimeout-td5294411.html
|
||||
if (!params.contains("-Xconversiontimeout")) {
|
||||
params.add(0, "-Xconversiontimeout");
|
||||
params.add(1, "100000");
|
||||
}
|
||||
return params.toArray(new String[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkConfiguration(Issues issues) {
|
||||
super.checkConfiguration(issues);
|
||||
if (!antlrTool.isWorkable()) {
|
||||
issues.addError(
|
||||
"\n\n*ATTENTION*\nIt is highly recommended to use ANTLR's parser generator (get it from 'http://xtext.itemis.com/'). \nAs an alternative to ANTLR you could also use the alternative implementation shipped with Xtext.\nTo do so use the generator fragment 'org.eclipse.xtext.generator.parser.packrat.PackratParserFragment' in your mwe2 file instead.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate() {
|
||||
checkGrammar();
|
||||
doGenerate();
|
||||
}
|
||||
|
||||
protected abstract void doGenerate();
|
||||
|
||||
protected void checkGrammar() {
|
||||
if (!hasProductionRules(getGrammar())) {
|
||||
throw new IllegalArgumentException(
|
||||
"You may not generate an ANTLR parser for a grammar without production rules.");
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean hasProductionRules(Grammar grammar) {
|
||||
AbstractRule firstRule = grammar.getRules().get(0);
|
||||
return firstRule instanceof ParserRule && !GrammarUtil.isDatatypeRule((ParserRule) firstRule);
|
||||
}
|
||||
|
||||
protected void splitLexerClassFile(IXtextGeneratorFileSystemAccess fsa, TypeReference lexer) {
|
||||
String content = fsa.readTextFile(lexer.getJavaPath()).toString();
|
||||
AntlrLexerSplitter splitter = new AntlrLexerSplitter(content);
|
||||
splitter.setCasesPerSpecialStateSwitch(options.getCasesPerSpecialStateSwitch());
|
||||
fsa.generateFile(lexer.getJavaPath(), splitter.transform());
|
||||
}
|
||||
|
||||
protected void splitParserClassFile(IXtextGeneratorFileSystemAccess fsa, TypeReference parser) {
|
||||
String content = fsa.readTextFile(parser.getJavaPath()).toString();
|
||||
AntlrParserSplitter splitter = new AntlrParserSplitter(content, getOptions().getFieldsPerClass());
|
||||
PartialClassExtractor extractor = new PartialClassExtractor(splitter.transform(), getOptions().getMethodsPerClass());
|
||||
fsa.generateFile(parser.getJavaPath(), extractor.transform());
|
||||
}
|
||||
|
||||
protected void simplifyUnorderedGroupPredicatesIfRequired(Grammar grammar, IXtextGeneratorFileSystemAccess fsa,
|
||||
TypeReference parser) {
|
||||
if (containsUnorderedGroup(grammar) || hasParameterizedRules(grammar)) {
|
||||
simplifyUnorderedGroupPredicates(fsa, parser);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean hasParameterizedRules(Grammar grammar) {
|
||||
for (ParserRule rule : GrammarUtil.allParserRules(grammar)) {
|
||||
if (!rule.getParameters().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void simplifyUnorderedGroupPredicates(IXtextGeneratorFileSystemAccess fsa, TypeReference parser) {
|
||||
String content = fsa.readTextFile(parser.getJavaPath()).toString();
|
||||
UnorderedGroupsSplitter splitter = new UnorderedGroupsSplitter(content);
|
||||
String transformed = splitter.transform();
|
||||
SyntacticPredicateFixup fixup = new SyntacticPredicateFixup(transformed);
|
||||
transformed = fixup.transform();
|
||||
BacktrackingGuardForUnorderedGroupsRemover remover = new BacktrackingGuardForUnorderedGroupsRemover(
|
||||
transformed);
|
||||
String newContent = remover.transform();
|
||||
fsa.generateFile(parser.getJavaPath(), newContent);
|
||||
}
|
||||
|
||||
protected void suppressWarnings(IXtextGeneratorFileSystemAccess fsa, TypeReference type) {
|
||||
String content = fsa.readTextFile(type.getJavaPath()).toString();
|
||||
String newContent = new SuppressWarningsProcessor().process(content);
|
||||
fsa.generateFile(type.getJavaPath(), newContent);
|
||||
}
|
||||
|
||||
protected void suppressWarnings(IXtextGeneratorFileSystemAccess fsa, TypeReference... types) {
|
||||
if (types != null) {
|
||||
for (TypeReference it : types) {
|
||||
suppressWarnings(fsa, it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void normalizeLineDelimiters(IXtextGeneratorFileSystemAccess fsa, TypeReference type) {
|
||||
String content = fsa.readTextFile(type.getJavaPath()).toString();
|
||||
content = newLineNormalizer.postProcess(fsa.getURI(type.getJavaPath()), content).toString();
|
||||
content = content.replaceAll("\"\\+(\\r)?\\n\\s+\"", "");
|
||||
fsa.generateFile(type.getJavaPath(), content);
|
||||
}
|
||||
|
||||
protected void normalizeLineDelimiters(IXtextGeneratorFileSystemAccess fsa, TypeReference... types) {
|
||||
if (types != null) {
|
||||
for (TypeReference it : types) {
|
||||
normalizeLineDelimiters(fsa, it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void normalizeTokens(IXtextGeneratorFileSystemAccess fsa, String tokenFile) {
|
||||
String content = fsa.readTextFile(tokenFile).toString();
|
||||
content = newLineNormalizer.postProcess(fsa.getURI(tokenFile), content).toString();
|
||||
List<String> splitted = Strings.split(content, codeConfig.getLineDelimiter());
|
||||
Collections.sort(splitted);
|
||||
content = Strings.concat(codeConfig.getLineDelimiter(), splitted) + codeConfig.getLineDelimiter();
|
||||
fsa.generateFile(tokenFile, content);
|
||||
}
|
||||
|
||||
protected void splitParserAndLexerIfEnabled(IXtextGeneratorFileSystemAccess fsa, TypeReference parser,
|
||||
TypeReference lexer) {
|
||||
improveCodeQuality(fsa, lexer, parser);
|
||||
if (getOptions().isClassSplitting()) {
|
||||
splitLexerClassFile(fsa, lexer);
|
||||
splitParserClassFile(fsa, parser);
|
||||
}
|
||||
}
|
||||
|
||||
protected void improveCodeQuality(IXtextGeneratorFileSystemAccess fsa, TypeReference lexer, TypeReference parser) {
|
||||
improveLexerCodeQuality(fsa, lexer);
|
||||
improveParserCodeQuality(fsa, parser);
|
||||
}
|
||||
|
||||
protected void improveParserCodeQuality(IXtextGeneratorFileSystemAccess fsa, TypeReference parser) {
|
||||
String parserContent = fsa.readTextFile(parser.getJavaPath()).toString();
|
||||
parserContent = codeQualityHelper.stripUnnecessaryComments(parserContent, options);
|
||||
parserContent = codeQualityHelper.removeDuplicateBitsets(parserContent, options);
|
||||
parserContent = codeQualityHelper.removeDuplicateDFAs(parserContent, options);
|
||||
fsa.generateFile(parser.getJavaPath(), parserContent);
|
||||
}
|
||||
|
||||
protected void improveLexerCodeQuality(IXtextGeneratorFileSystemAccess fsa, TypeReference lexer) {
|
||||
String lexerContent = fsa.readTextFile(lexer.getJavaPath()).toString();
|
||||
lexerContent = codeQualityHelper.stripUnnecessaryComments(lexerContent, options);
|
||||
fsa.generateFile(lexer.getJavaPath(), lexerContent);
|
||||
}
|
||||
|
||||
protected void cleanupLexerTokensFile(AntlrGrammar lexerGrammar, KeywordHelper helper,
|
||||
IXtextGeneratorFileSystemAccess fsa) {
|
||||
try {
|
||||
if (options.isBacktrackLexer()) {
|
||||
MutableTokenDefProvider provider = createLexerTokensProvider(lexerGrammar, helper, fsa);
|
||||
Iterator<Map.Entry<Integer, String>> entries = provider.getTokenDefMap().entrySet().iterator();
|
||||
while (entries.hasNext()) {
|
||||
String value = entries.next().getValue();
|
||||
if (!helper.isKeywordRule(value) && !value.startsWith("RULE_") && !value.startsWith("SUPER_")) {
|
||||
entries.remove();
|
||||
}
|
||||
}
|
||||
CharArrayWriter writer = new CharArrayWriter();
|
||||
provider.writeTokenFile(new PrintWriter(writer));
|
||||
fsa.generateFile(lexerGrammar.getTokensFileName(), new String(writer.toCharArray()));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected MutableTokenDefProvider createLexerTokensProvider(AntlrGrammar lexerGrammar, KeywordHelper helper,
|
||||
IXtextGeneratorFileSystemAccess fsa) {
|
||||
MutableTokenDefProvider provider = new MutableTokenDefProvider(helper,
|
||||
Charset.forName(codeConfig.getEncoding()));
|
||||
provider.setAntlrTokenFileProvider(() -> {
|
||||
return fsa.readBinaryFile(lexerGrammar.getTokensFileName());
|
||||
});
|
||||
return provider;
|
||||
}
|
||||
|
||||
protected void cleanupParserTokensFile(AntlrGrammar lexerGrammar, AntlrGrammar parserGrammar, KeywordHelper helper,
|
||||
IXtextGeneratorFileSystemAccess fsa) {
|
||||
try {
|
||||
MutableTokenDefProvider provider = createLexerTokensProvider(lexerGrammar, helper, fsa);
|
||||
for (Map.Entry<Integer, String> entry : provider.getTokenDefMap().entrySet()) {
|
||||
String value = entry.getValue();
|
||||
if (helper.isKeywordRule(value)) {
|
||||
String keywordAsAntlrString = AntlrGrammarGenUtil.toAntlrString(helper.getKeywordValue(value));
|
||||
entry.setValue("'" + keywordAsAntlrString + "'");
|
||||
} else {
|
||||
if (value.startsWith("'")) {
|
||||
entry.setValue("'" + AntlrGrammarGenUtil.toAntlrString(value) + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
CharArrayWriter writer = new CharArrayWriter();
|
||||
provider.writeTokenFile(new PrintWriter(writer));
|
||||
fsa.generateFile(parserGrammar.getTokensFileName(), new String(writer.toCharArray()));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void removeBackTrackingGuards(IXtextGeneratorFileSystemAccess fsa, TypeReference parser,
|
||||
int lookaheadThreshold) {
|
||||
String content = fsa.readTextFile(parser.getJavaPath()).toString();
|
||||
BacktrackingGuardRemover remover = new BacktrackingGuardRemover(content, lookaheadThreshold);
|
||||
String newContent = remover.transform();
|
||||
fsa.generateFile(parser.getJavaPath(), newContent);
|
||||
}
|
||||
|
||||
protected boolean containsUnorderedGroup(Grammar grammar) {
|
||||
for (ParserRule rule : GrammarUtil.allParserRules(grammar)) {
|
||||
if (Iterators.filter(rule.eAllContents(), UnorderedGroup.class).hasNext()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected AntlrToolFacade getAntlrTool() {
|
||||
return antlrTool;
|
||||
}
|
||||
|
||||
protected AntlrCodeQualityHelper getCodeQualityHelper() {
|
||||
return codeQualityHelper;
|
||||
}
|
||||
|
||||
protected LineSeparatorHarmonizer getNewLineNormalizer() {
|
||||
return newLineNormalizer;
|
||||
}
|
||||
|
||||
protected CodeConfig getCodeConfig() {
|
||||
return codeConfig;
|
||||
}
|
||||
|
||||
public AntlrOptions getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public void setOptions(AntlrOptions options) {
|
||||
this.options = options;
|
||||
}
|
||||
}
|
|
@ -1,244 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2015 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.xtext.generator.parser.antlr
|
||||
|
||||
import com.google.common.collect.Iterators
|
||||
import com.google.common.collect.Lists
|
||||
import com.google.inject.Inject
|
||||
import java.io.CharArrayWriter
|
||||
import java.io.PrintWriter
|
||||
import java.nio.charset.Charset
|
||||
import java.util.Collections
|
||||
import org.eclipse.xtend.lib.annotations.Accessors
|
||||
import org.eclipse.xtext.AbstractRule
|
||||
import org.eclipse.xtext.Grammar
|
||||
import org.eclipse.xtext.GrammarUtil
|
||||
import org.eclipse.xtext.ParserRule
|
||||
import org.eclipse.xtext.UnorderedGroup
|
||||
import org.eclipse.xtext.generator.LineSeparatorHarmonizer
|
||||
import org.eclipse.xtext.util.Strings
|
||||
import org.eclipse.xtext.xtext.generator.AbstractXtextGeneratorFragment
|
||||
import org.eclipse.xtext.xtext.generator.CodeConfig
|
||||
import org.eclipse.xtext.xtext.generator.Issues
|
||||
import org.eclipse.xtext.xtext.generator.model.IXtextGeneratorFileSystemAccess
|
||||
import org.eclipse.xtext.xtext.generator.model.TypeReference
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.postProcessing.SuppressWarningsProcessor
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.AntlrCodeQualityHelper
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.AntlrLexerSplitter
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.AntlrParserSplitter
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.BacktrackingGuardForUnorderedGroupsRemover
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.BacktrackingGuardRemover
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.PartialClassExtractor
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.SyntacticPredicateFixup
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.UnorderedGroupsSplitter
|
||||
|
||||
abstract class AbstractAntlrGeneratorFragment2 extends AbstractXtextGeneratorFragment {
|
||||
@Inject @Accessors(PROTECTED_GETTER) AntlrToolFacade antlrTool
|
||||
@Inject @Accessors(PROTECTED_GETTER) AntlrCodeQualityHelper codeQualityHelper
|
||||
@Inject @Accessors(PROTECTED_GETTER) LineSeparatorHarmonizer newLineNormalizer
|
||||
@Inject @Accessors(PROTECTED_GETTER) CodeConfig codeConfig
|
||||
|
||||
@Accessors AntlrOptions options = new AntlrOptions
|
||||
val antlrParams = <String>newArrayList
|
||||
|
||||
def void addAntlrParam(String param) {
|
||||
antlrParams.add(param)
|
||||
}
|
||||
|
||||
def String[] getAntlrParams() {
|
||||
var params = Lists.newArrayList(antlrParams)
|
||||
// setting the default conversion timeout to 100secs.
|
||||
// There seem to be no practical situations where the NFA conversion would hang,
|
||||
// so Terence suggested here [1] to remove the option all together
|
||||
// [1] - http://antlr.1301665.n2.nabble.com/Xconversiontimeout-td5294411.html
|
||||
if (!params.contains("-Xconversiontimeout")) {
|
||||
params.add(0, "-Xconversiontimeout")
|
||||
params.add(1, "100000")
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
override void checkConfiguration(Issues issues) {
|
||||
super.checkConfiguration(issues)
|
||||
if (!antlrTool.isWorkable) {
|
||||
issues.addError("\n\n*ATTENTION*\nIt is highly recommended to use ANTLR's parser generator (get it from 'http://xtext.itemis.com/'). \nAs an alternative to ANTLR you could also use the alternative implementation shipped with Xtext.\nTo do so use the generator fragment 'org.eclipse.xtext.generator.parser.packrat.PackratParserFragment' in your mwe2 file instead.")
|
||||
}
|
||||
}
|
||||
|
||||
override void generate() {
|
||||
checkGrammar()
|
||||
doGenerate()
|
||||
}
|
||||
|
||||
def protected abstract void doGenerate()
|
||||
|
||||
def protected void checkGrammar() {
|
||||
if(!hasProductionRules(getGrammar()))
|
||||
throw new IllegalArgumentException("You may not generate an ANTLR parser for a grammar without production rules.")
|
||||
}
|
||||
|
||||
def protected boolean hasProductionRules(Grammar grammar) {
|
||||
var AbstractRule firstRule = grammar.getRules().get(0)
|
||||
return firstRule instanceof ParserRule && !GrammarUtil::isDatatypeRule(firstRule as ParserRule)
|
||||
}
|
||||
|
||||
def protected void splitLexerClassFile(IXtextGeneratorFileSystemAccess fsa, TypeReference lexer) {
|
||||
val content = fsa.readTextFile(lexer.javaPath).toString
|
||||
var AntlrLexerSplitter splitter = new AntlrLexerSplitter(content)
|
||||
splitter.setCasesPerSpecialStateSwitch(options.getCasesPerSpecialStateSwitch());
|
||||
fsa.generateFile(lexer.javaPath, splitter.transform)
|
||||
}
|
||||
|
||||
def protected void splitParserClassFile(IXtextGeneratorFileSystemAccess fsa, TypeReference parser) {
|
||||
val content = fsa.readTextFile(parser.javaPath).toString
|
||||
val splitter = new AntlrParserSplitter(content, getOptions.fieldsPerClass)
|
||||
val extractor = new PartialClassExtractor(splitter.transform, getOptions.methodsPerClass)
|
||||
fsa.generateFile(parser.javaPath, extractor.transform)
|
||||
}
|
||||
|
||||
def protected void simplifyUnorderedGroupPredicatesIfRequired(Grammar grammar, IXtextGeneratorFileSystemAccess fsa, TypeReference parser) {
|
||||
if (containsUnorderedGroup(grammar) || hasParameterizedRules(grammar)) {
|
||||
simplifyUnorderedGroupPredicates(fsa, parser)
|
||||
}
|
||||
}
|
||||
|
||||
def protected boolean hasParameterizedRules(Grammar grammar) {
|
||||
for (ParserRule rule : GrammarUtil::allParserRules(grammar)) {
|
||||
if (!rule.getParameters().isEmpty()) {
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
def protected void simplifyUnorderedGroupPredicates(IXtextGeneratorFileSystemAccess fsa, TypeReference parser) {
|
||||
val content = fsa.readTextFile(parser.javaPath).toString
|
||||
var UnorderedGroupsSplitter splitter = new UnorderedGroupsSplitter(content)
|
||||
var String transformed = splitter.transform()
|
||||
var SyntacticPredicateFixup fixup = new SyntacticPredicateFixup(transformed)
|
||||
transformed = fixup.transform()
|
||||
var BacktrackingGuardForUnorderedGroupsRemover remover = new BacktrackingGuardForUnorderedGroupsRemover(transformed)
|
||||
var String newContent = remover.transform()
|
||||
fsa.generateFile(parser.javaPath, newContent)
|
||||
}
|
||||
|
||||
def protected void suppressWarnings(IXtextGeneratorFileSystemAccess fsa, TypeReference type) {
|
||||
val content = fsa.readTextFile(type.javaPath).toString
|
||||
val newContent = new SuppressWarningsProcessor().process(content)
|
||||
fsa.generateFile(type.javaPath, newContent)
|
||||
}
|
||||
def protected void suppressWarnings(IXtextGeneratorFileSystemAccess fsa, TypeReference... types) {
|
||||
types.forEach[suppressWarnings(fsa, it)]
|
||||
}
|
||||
|
||||
def protected void normalizeLineDelimiters(IXtextGeneratorFileSystemAccess fsa, TypeReference type) {
|
||||
var String content = fsa.readTextFile(type.javaPath).toString
|
||||
content = newLineNormalizer.postProcess(fsa.getURI(type.javaPath), content).toString
|
||||
// Antlr tries to outsmart us by using a line length that depends on the system
|
||||
// line delimiter when it splits a very long String (encoded DFA) into a
|
||||
// string concatenation
|
||||
// Here we join these lines again.
|
||||
content = content.replaceAll("\"\\+(\\r)?\\n\\s+\"", "")
|
||||
fsa.generateFile(type.javaPath, content)
|
||||
}
|
||||
|
||||
def protected void normalizeLineDelimiters(IXtextGeneratorFileSystemAccess fsa, TypeReference... types) {
|
||||
types.forEach[normalizeLineDelimiters(fsa, it)]
|
||||
}
|
||||
|
||||
def protected void normalizeTokens(IXtextGeneratorFileSystemAccess fsa, String tokenFile) {
|
||||
var content = fsa.readTextFile(tokenFile).toString
|
||||
content = newLineNormalizer.postProcess(fsa.getURI(tokenFile), content).toString
|
||||
val splitted = Strings.split(content, codeConfig.lineDelimiter)
|
||||
Collections.sort(splitted)
|
||||
content = Strings.concat(codeConfig.lineDelimiter, splitted) + codeConfig.lineDelimiter
|
||||
fsa.generateFile(tokenFile, content)
|
||||
}
|
||||
|
||||
def protected void splitParserAndLexerIfEnabled(IXtextGeneratorFileSystemAccess fsa, TypeReference parser, TypeReference lexer) {
|
||||
improveCodeQuality(fsa, lexer, parser)
|
||||
if (getOptions().isClassSplitting()) {
|
||||
splitLexerClassFile(fsa, lexer)
|
||||
splitParserClassFile(fsa, parser)
|
||||
}
|
||||
}
|
||||
|
||||
def protected void improveCodeQuality(IXtextGeneratorFileSystemAccess fsa, TypeReference lexer, TypeReference parser) {
|
||||
improveLexerCodeQuality(fsa, lexer)
|
||||
improveParserCodeQuality(fsa, parser)
|
||||
}
|
||||
|
||||
def protected void improveParserCodeQuality(IXtextGeneratorFileSystemAccess fsa, TypeReference parser) {
|
||||
var parserContent = fsa.readTextFile(parser.javaPath).toString
|
||||
parserContent = codeQualityHelper.stripUnnecessaryComments(parserContent, options)
|
||||
parserContent = codeQualityHelper.removeDuplicateBitsets(parserContent, options)
|
||||
parserContent = codeQualityHelper.removeDuplicateDFAs(parserContent, options)
|
||||
fsa.generateFile(parser.javaPath, parserContent)
|
||||
}
|
||||
|
||||
def protected void improveLexerCodeQuality(IXtextGeneratorFileSystemAccess fsa, TypeReference lexer) {
|
||||
var lexerContent = fsa.readTextFile(lexer.javaPath).toString
|
||||
lexerContent = codeQualityHelper.stripUnnecessaryComments(lexerContent, options)
|
||||
fsa.generateFile(lexer.javaPath, lexerContent)
|
||||
}
|
||||
|
||||
def protected void cleanupLexerTokensFile(AntlrGrammar lexerGrammar, KeywordHelper helper, IXtextGeneratorFileSystemAccess fsa) {
|
||||
if (options.backtrackLexer) {
|
||||
val provider = createLexerTokensProvider(lexerGrammar, helper, fsa)
|
||||
val entries = provider.tokenDefMap.entrySet.iterator
|
||||
while (entries.hasNext) {
|
||||
val value = entries.next.value
|
||||
if(!helper.isKeywordRule(value) && !value.startsWith("RULE_") && !value.startsWith("SUPER_"))
|
||||
entries.remove
|
||||
}
|
||||
val writer = new CharArrayWriter
|
||||
provider.writeTokenFile(new PrintWriter(writer))
|
||||
fsa.generateFile(lexerGrammar.tokensFileName, new String(writer.toCharArray))
|
||||
}
|
||||
}
|
||||
|
||||
def protected MutableTokenDefProvider createLexerTokensProvider(AntlrGrammar lexerGrammar, KeywordHelper helper, IXtextGeneratorFileSystemAccess fsa) {
|
||||
val provider = new MutableTokenDefProvider(helper, Charset.forName(codeConfig.encoding))
|
||||
provider.antlrTokenFileProvider = [fsa.readBinaryFile(lexerGrammar.tokensFileName)]
|
||||
return provider
|
||||
}
|
||||
|
||||
def protected void cleanupParserTokensFile(AntlrGrammar lexerGrammar, AntlrGrammar parserGrammar, KeywordHelper helper, IXtextGeneratorFileSystemAccess fsa) {
|
||||
val provider= createLexerTokensProvider(lexerGrammar, helper, fsa)
|
||||
for (entry : provider.tokenDefMap.entrySet) {
|
||||
val value = entry.value
|
||||
if (helper.isKeywordRule(value)) {
|
||||
val keywordAsAntlrString = AntlrGrammarGenUtil.toAntlrString(helper.getKeywordValue(value))
|
||||
entry.setValue("'" + keywordAsAntlrString + "'")
|
||||
} else if (value.startsWith("'")) {
|
||||
entry.setValue("'" + AntlrGrammarGenUtil.toAntlrString(value) + "'")
|
||||
}
|
||||
}
|
||||
val writer = new CharArrayWriter
|
||||
provider.writeTokenFile(new PrintWriter(writer))
|
||||
fsa.generateFile(parserGrammar.tokensFileName, new String(writer.toCharArray))
|
||||
}
|
||||
|
||||
def protected void removeBackTrackingGuards(IXtextGeneratorFileSystemAccess fsa, TypeReference parser, int lookaheadThreshold) {
|
||||
val content = fsa.readTextFile(parser.javaPath).toString
|
||||
val remover = new BacktrackingGuardRemover(content, lookaheadThreshold)
|
||||
val newContent = remover.transform
|
||||
fsa.generateFile(parser.javaPath, newContent)
|
||||
}
|
||||
|
||||
def protected boolean containsUnorderedGroup(Grammar grammar) {
|
||||
for (ParserRule rule : GrammarUtil::allParserRules(grammar)) {
|
||||
if (Iterators::filter(rule.eAllContents(), UnorderedGroup).hasNext()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
* Copyright (c) 2015, 2020 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.xtext.generator.parser.antlr;
|
||||
|
||||
import org.eclipse.xtext.Grammar;
|
||||
import org.eclipse.xtext.GrammarUtil;
|
||||
import org.eclipse.xtext.xtext.generator.XtextGeneratorNaming;
|
||||
import org.eclipse.xtext.xtext.generator.model.TypeReference;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
public class GrammarNaming {
|
||||
@Inject
|
||||
private XtextGeneratorNaming xtextGeneratorNaming;
|
||||
|
||||
public boolean isCombinedGrammar(Grammar it) {
|
||||
return CombinedGrammarMarker.findInEmfObject(it).isCombinedGrammar();
|
||||
}
|
||||
|
||||
protected String getParserPackage(Grammar it) {
|
||||
return xtextGeneratorNaming.getRuntimeBasePackage(it) + ".parser.antlr";
|
||||
}
|
||||
|
||||
protected String getInternalParserPackage(Grammar it) {
|
||||
return getParserPackage(it) + ".internal";
|
||||
}
|
||||
|
||||
protected String getInternalLexerPackage(Grammar it) {
|
||||
return getParserPackage(it) + ".lexer";
|
||||
}
|
||||
|
||||
public AntlrGrammar getParserGrammar(Grammar it) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(getGrammarNamePrefix(it));
|
||||
builder.append("Internal");
|
||||
builder.append(GrammarUtil.getSimpleName(it));
|
||||
if (!isCombinedGrammar(it)) {
|
||||
builder.append("Parser");
|
||||
}
|
||||
return new AntlrGrammar(getInternalParserPackage(it), builder.toString());
|
||||
}
|
||||
|
||||
public AntlrGrammar getLexerGrammar(Grammar it) {
|
||||
if (isCombinedGrammar(it)) {
|
||||
return getParserGrammar(it);
|
||||
} else {
|
||||
return new AntlrGrammar(getInternalLexerPackage(it),
|
||||
getGrammarNamePrefix(it) + "Internal" + GrammarUtil.getSimpleName(it) + "Lexer");
|
||||
}
|
||||
}
|
||||
|
||||
protected String getGrammarNamePrefix(Grammar it) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public TypeReference getLexerClass(Grammar it) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(getLexerGrammar(it).getSimpleName());
|
||||
if (isCombinedGrammar(it)) {
|
||||
builder.append("Lexer");
|
||||
}
|
||||
return new TypeReference(getLexerGrammar(it).getPackageName(), builder.toString());
|
||||
}
|
||||
|
||||
public TypeReference getLexerSuperClass(Grammar it) {
|
||||
return new TypeReference("org.eclipse.xtext.parser.antlr.Lexer");
|
||||
}
|
||||
|
||||
public TypeReference getParserClass(Grammar it) {
|
||||
return new TypeReference(getParserPackage(it), GrammarUtil.getSimpleName(it) + "Parser");
|
||||
}
|
||||
|
||||
public TypeReference getParserSuperClass(Grammar it, boolean partialParsing) {
|
||||
return new TypeReference("org.eclipse.xtext.parser.antlr.AbstractAntlrParser");
|
||||
}
|
||||
|
||||
public TypeReference getInternalParserClass(Grammar it) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(getParserGrammar(it).getSimpleName());
|
||||
if (isCombinedGrammar(it)) {
|
||||
builder.append("Parser");
|
||||
}
|
||||
return new TypeReference(getParserGrammar(it).getPackageName(), builder.toString());
|
||||
}
|
||||
|
||||
public TypeReference getInternalParserSuperClass(Grammar it) {
|
||||
return new TypeReference("org.eclipse.xtext.parser.antlr.AbstractInternalAntlrParser");
|
||||
}
|
||||
|
||||
public TypeReference getAntlrTokenFileProviderClass(Grammar it) {
|
||||
return new TypeReference(getParserPackage(it), GrammarUtil.getSimpleName(it) + "AntlrTokenFileProvider");
|
||||
}
|
||||
|
||||
public TypeReference getTokenSourceClass(Grammar it) {
|
||||
return new TypeReference(getParserPackage(it), GrammarUtil.getSimpleName(it) + "TokenSource");
|
||||
}
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2015 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.xtext.generator.parser.antlr
|
||||
|
||||
import com.google.inject.Inject
|
||||
import com.google.inject.Singleton
|
||||
import org.eclipse.xtext.Grammar
|
||||
import org.eclipse.xtext.xtext.generator.XtextGeneratorNaming
|
||||
import org.eclipse.xtext.xtext.generator.model.TypeReference
|
||||
|
||||
import static extension org.eclipse.xtext.GrammarUtil.*
|
||||
|
||||
@Singleton
|
||||
class GrammarNaming {
|
||||
|
||||
@Inject
|
||||
extension XtextGeneratorNaming
|
||||
|
||||
def isCombinedGrammar(Grammar it) {
|
||||
CombinedGrammarMarker.findInEmfObject(it).isCombinedGrammar
|
||||
}
|
||||
|
||||
protected def String getParserPackage(Grammar it) {
|
||||
runtimeBasePackage + ".parser.antlr"
|
||||
}
|
||||
|
||||
protected def String getInternalParserPackage(Grammar it) {
|
||||
parserPackage + ".internal"
|
||||
}
|
||||
|
||||
protected def String getInternalLexerPackage(Grammar it) {
|
||||
parserPackage + ".lexer"
|
||||
}
|
||||
|
||||
def AntlrGrammar getParserGrammar(Grammar it) {
|
||||
new AntlrGrammar(internalParserPackage, '''«grammarNamePrefix»Internal«simpleName»«IF !combinedGrammar»Parser«ENDIF»''')
|
||||
}
|
||||
|
||||
def AntlrGrammar getLexerGrammar(Grammar it) {
|
||||
if (combinedGrammar) {
|
||||
getParserGrammar
|
||||
} else {
|
||||
new AntlrGrammar(internalLexerPackage, '''«grammarNamePrefix»Internal«simpleName»Lexer''')
|
||||
}
|
||||
}
|
||||
|
||||
protected def String getGrammarNamePrefix(Grammar it) {
|
||||
""
|
||||
}
|
||||
|
||||
def TypeReference getLexerClass(Grammar it) {
|
||||
new TypeReference(lexerGrammar.packageName, '''«lexerGrammar.simpleName»«IF combinedGrammar»Lexer«ENDIF»''')
|
||||
}
|
||||
|
||||
def TypeReference getLexerSuperClass(Grammar it) {
|
||||
new TypeReference("org.eclipse.xtext.parser.antlr.Lexer")
|
||||
}
|
||||
|
||||
def TypeReference getParserClass(Grammar it) {
|
||||
new TypeReference(parserPackage, '''«simpleName»Parser''')
|
||||
}
|
||||
|
||||
def TypeReference getParserSuperClass(Grammar it, boolean partialParsing) {
|
||||
new TypeReference("org.eclipse.xtext.parser.antlr.AbstractAntlrParser")
|
||||
}
|
||||
|
||||
def TypeReference getInternalParserClass(Grammar it) {
|
||||
new TypeReference(parserGrammar.packageName, '''«parserGrammar.simpleName»«IF combinedGrammar»Parser«ENDIF»''')
|
||||
}
|
||||
|
||||
def TypeReference getInternalParserSuperClass(Grammar it) {
|
||||
new TypeReference("org.eclipse.xtext.parser.antlr.AbstractInternalAntlrParser")
|
||||
}
|
||||
|
||||
def TypeReference getAntlrTokenFileProviderClass(Grammar it) {
|
||||
new TypeReference(parserPackage, '''«simpleName»AntlrTokenFileProvider''')
|
||||
}
|
||||
|
||||
def TypeReference getTokenSourceClass(Grammar it) {
|
||||
new TypeReference(parserPackage, simpleName + "TokenSource")
|
||||
}
|
||||
|
||||
}
|
|
@ -1,457 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2015, 2020 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.xtext.generator;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.inject.Binder;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Provider;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.eclipse.emf.common.util.Diagnostic;
|
||||
import org.eclipse.emf.common.util.DiagnosticChain;
|
||||
import org.eclipse.emf.common.util.TreeIterator;
|
||||
import org.eclipse.emf.common.util.URI;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.EReference;
|
||||
import org.eclipse.emf.ecore.EValidator;
|
||||
import org.eclipse.emf.ecore.resource.Resource;
|
||||
import org.eclipse.emf.ecore.resource.ResourceSet;
|
||||
import org.eclipse.emf.ecore.util.EcoreUtil;
|
||||
import org.eclipse.xtend.lib.annotations.AccessorType;
|
||||
import org.eclipse.xtend.lib.annotations.Accessors;
|
||||
import org.eclipse.xtext.AbstractMetamodelDeclaration;
|
||||
import org.eclipse.xtext.Grammar;
|
||||
import org.eclipse.xtext.GrammarUtil;
|
||||
import org.eclipse.xtext.ReferencedMetamodel;
|
||||
import org.eclipse.xtext.XtextPackage;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
|
||||
import org.eclipse.xtext.resource.IResourceDescription;
|
||||
import org.eclipse.xtext.resource.IResourceServiceProvider;
|
||||
import org.eclipse.xtext.resource.XtextResource;
|
||||
import org.eclipse.xtext.resource.impl.ResourceDescriptionsData;
|
||||
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
|
||||
import org.eclipse.xtext.xbase.lib.Conversions;
|
||||
import org.eclipse.xtext.xbase.lib.IterableExtensions;
|
||||
import org.eclipse.xtext.xbase.lib.Pure;
|
||||
import org.eclipse.xtext.xtext.RuleNames;
|
||||
import org.eclipse.xtext.xtext.generator.CodeConfig;
|
||||
import org.eclipse.xtext.xtext.generator.CompositeGeneratorFragment2;
|
||||
import org.eclipse.xtext.xtext.generator.IXtextGeneratorFragment;
|
||||
import org.eclipse.xtext.xtext.generator.IXtextGeneratorLanguage;
|
||||
import org.eclipse.xtext.xtext.generator.ImplicitFragment;
|
||||
import org.eclipse.xtext.xtext.generator.XtextGeneratorResourceSetInitializer;
|
||||
import org.eclipse.xtext.xtext.generator.model.GuiceModuleAccess;
|
||||
import org.eclipse.xtext.xtext.generator.model.StandaloneSetupAccess;
|
||||
import org.eclipse.xtext.xtext.generator.model.project.IXtextProjectConfig;
|
||||
|
||||
/**
|
||||
* Configuration for an Xtext language. Use this class if you need to specify exactly which generator
|
||||
* fragments you want to include, or alternatively {@link StandardLanguage} to work with the standard
|
||||
* fragments.
|
||||
*
|
||||
* <p>The most important property is {@code name}, which should be set to the language name exactly
|
||||
* as specified in the grammar file. If the default grammar resolution based on the name does not
|
||||
* work in your particular scenario, set the {@code grammarUri} property instead. Furthermore,
|
||||
* use {@code fileExtensions} to specify the file extensions for your language.</p>
|
||||
*
|
||||
* <p>Generator fragments can be added with the {@code fragment} property. See {@link StandardLanguage}
|
||||
* for a list of useful fragments.</p>
|
||||
*
|
||||
* @noextend This class should not be extended by clients.
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class XtextGeneratorLanguage extends CompositeGeneratorFragment2 implements IXtextGeneratorLanguage {
|
||||
private static final Logger LOG = Logger.getLogger(XtextGeneratorLanguage.class);
|
||||
|
||||
private String grammarUri;
|
||||
|
||||
private String name;
|
||||
|
||||
private Boolean generateXtendStubs;
|
||||
|
||||
@Accessors(AccessorType.PUBLIC_GETTER)
|
||||
private Grammar grammar;
|
||||
|
||||
@Accessors(AccessorType.PUBLIC_GETTER)
|
||||
private RuleNames ruleNames;
|
||||
|
||||
@Accessors(AccessorType.PUBLIC_GETTER)
|
||||
private List<String> fileExtensions;
|
||||
|
||||
@Accessors(AccessorType.PUBLIC_GETTER)
|
||||
private List<String> referencedResources = CollectionLiterals.<String>newArrayList();
|
||||
|
||||
@Accessors
|
||||
private ResourceSet resourceSet;
|
||||
|
||||
@Accessors
|
||||
private com.google.inject.Module guiceModule = ((com.google.inject.Module) (Binder it) -> {
|
||||
});
|
||||
|
||||
@Accessors
|
||||
private final StandaloneSetupAccess runtimeGenSetup = new StandaloneSetupAccess();
|
||||
|
||||
@Accessors
|
||||
private final GuiceModuleAccess runtimeGenModule = new GuiceModuleAccess();
|
||||
|
||||
@Accessors
|
||||
private final GuiceModuleAccess ideGenModule = new GuiceModuleAccess();
|
||||
|
||||
@Accessors
|
||||
private final GuiceModuleAccess eclipsePluginGenModule = new GuiceModuleAccess();
|
||||
|
||||
@Accessors
|
||||
private final GuiceModuleAccess webGenModule = new GuiceModuleAccess();
|
||||
|
||||
@Inject
|
||||
private Provider<ResourceSet> resourceSetProvider;
|
||||
|
||||
@Inject
|
||||
private IXtextProjectConfig projectConfig;
|
||||
|
||||
@Inject
|
||||
private CodeConfig codeConfig;
|
||||
|
||||
@Inject
|
||||
private XtextGeneratorResourceSetInitializer resourceSetInitializer;
|
||||
|
||||
/**
|
||||
* The URI of the grammar file. Use this property if the automatic grammar resolution based on {@link #setName(String)}
|
||||
* does not work in your particular scenario.
|
||||
*/
|
||||
public void setGrammarUri(final String uri) {
|
||||
this.grammarUri = uri;
|
||||
}
|
||||
|
||||
public String getGrammarUri() {
|
||||
String _elvis = null;
|
||||
if (this.grammarUri != null) {
|
||||
_elvis = this.grammarUri;
|
||||
} else {
|
||||
String _path = this.projectConfig.getRuntime().getSrc().getPath();
|
||||
String _replace = this.name.replace(".", "/");
|
||||
String _plus = (_replace + ".xtext");
|
||||
String _string = new File(_path, _plus).toURI().toString();
|
||||
_elvis = _string;
|
||||
}
|
||||
return _elvis;
|
||||
}
|
||||
|
||||
/**
|
||||
* The language name exactly as specified in the grammar.
|
||||
*/
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Either a single file extension or a comma-separated list of extensions for which the language
|
||||
* shall be registered.
|
||||
*/
|
||||
public void setFileExtensions(final String fileExtensions) {
|
||||
this.fileExtensions = IterableExtensions.<String>toList(((Iterable<String>)Conversions.doWrapArray(fileExtensions.trim().split("\\s*,\\s*"))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a resource to be included in the resource set that will be used to load the grammar file.
|
||||
* This is often necessary if additional Ecore models are referenced by the grammar.
|
||||
*/
|
||||
public void addReferencedResource(final String referencedResource) {
|
||||
this.referencedResources.add(referencedResource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getFileExtensions() {
|
||||
if (((this.fileExtensions == null) || this.fileExtensions.isEmpty())) {
|
||||
this.setFileExtensions(GrammarUtil.getSimpleName(this.grammar).toLowerCase());
|
||||
XtextGeneratorLanguage.LOG.info((("No explicit fileExtensions configured. Using \'*." + this.fileExtensions) + "\'."));
|
||||
}
|
||||
return this.fileExtensions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link CodeConfig#setPreferXtendStubs(boolean)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public void setGenerateXtendStubs(final Boolean generateXtendStubs) {
|
||||
this.generateXtendStubs = generateXtendStubs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link CodeConfig#isPreferXtendStubs()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean isGenerateXtendStubs() {
|
||||
boolean _xifexpression = false;
|
||||
if ((this.generateXtendStubs != null)) {
|
||||
_xifexpression = this.generateXtendStubs.booleanValue();
|
||||
} else {
|
||||
_xifexpression = this.codeConfig.isPreferXtendStubs();
|
||||
}
|
||||
return _xifexpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final Injector injector) {
|
||||
this.getFragments().addAll(0, this.getImplicitFragments());
|
||||
injector.injectMembers(this);
|
||||
if ((this.resourceSet == null)) {
|
||||
this.resourceSet = this.resourceSetProvider.get();
|
||||
}
|
||||
this.resourceSetInitializer.initialize(this.resourceSet, this.referencedResources);
|
||||
boolean _isEmpty = this.resourceSet.getResources().isEmpty();
|
||||
boolean _not = (!_isEmpty);
|
||||
if (_not) {
|
||||
this.installIndex();
|
||||
{
|
||||
int i = 0;
|
||||
int size = this.resourceSet.getResources().size();
|
||||
boolean _while = (i < size);
|
||||
while (_while) {
|
||||
{
|
||||
final Resource res = this.resourceSet.getResources().get(i);
|
||||
boolean _isEmpty_1 = res.getContents().isEmpty();
|
||||
if (_isEmpty_1) {
|
||||
URI _uRI = res.getURI();
|
||||
String _plus = ("Error loading \'" + _uRI);
|
||||
String _plus_1 = (_plus + "\'");
|
||||
XtextGeneratorLanguage.LOG.error(_plus_1);
|
||||
} else {
|
||||
boolean _isEmpty_2 = res.getErrors().isEmpty();
|
||||
boolean _not_1 = (!_isEmpty_2);
|
||||
if (_not_1) {
|
||||
URI _uRI_1 = res.getURI();
|
||||
String _plus_2 = ("Error loading \'" + _uRI_1);
|
||||
String _plus_3 = (_plus_2 + "\':\n");
|
||||
String _join = Joiner.on("\n").join(res.getErrors());
|
||||
String _plus_4 = (_plus_3 + _join);
|
||||
XtextGeneratorLanguage.LOG.error(_plus_4);
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
_while = (i < size);
|
||||
}
|
||||
}
|
||||
EcoreUtil.resolveAll(this.resourceSet);
|
||||
}
|
||||
String _grammarUri = this.getGrammarUri();
|
||||
boolean _tripleEquals = (_grammarUri == null);
|
||||
if (_tripleEquals) {
|
||||
throw new IllegalStateException("No grammarUri or language name given");
|
||||
}
|
||||
Resource _resource = this.resourceSet.getResource(URI.createURI(this.getGrammarUri()), true);
|
||||
final XtextResource resource = ((XtextResource) _resource);
|
||||
boolean _isEmpty_1 = resource.getContents().isEmpty();
|
||||
if (_isEmpty_1) {
|
||||
String _grammarUri_1 = this.getGrammarUri();
|
||||
String _plus = ("Couldn\'t load grammar for \'" + _grammarUri_1);
|
||||
String _plus_1 = (_plus + "\'.");
|
||||
throw new IllegalArgumentException(_plus_1);
|
||||
}
|
||||
boolean _isEmpty_2 = resource.getErrors().isEmpty();
|
||||
boolean _not_1 = (!_isEmpty_2);
|
||||
if (_not_1) {
|
||||
XtextGeneratorLanguage.LOG.error(resource.getErrors());
|
||||
String _grammarUri_2 = this.getGrammarUri();
|
||||
String _plus_2 = ("Problem parsing \'" + _grammarUri_2);
|
||||
String _plus_3 = (_plus_2 + "\':\n");
|
||||
String _join = Joiner.on("\n").join(resource.getErrors());
|
||||
String _plus_4 = (_plus_3 + _join);
|
||||
throw new IllegalStateException(_plus_4);
|
||||
}
|
||||
EObject _get = resource.getContents().get(0);
|
||||
final Grammar grammar = ((Grammar) _get);
|
||||
this.validateGrammar(grammar);
|
||||
this.initialize(grammar);
|
||||
super.initialize(injector);
|
||||
}
|
||||
|
||||
protected List<? extends IXtextGeneratorFragment> getImplicitFragments() {
|
||||
final ArrayList<ImplicitFragment> fragments = CollectionLiterals.<ImplicitFragment>newArrayList();
|
||||
ImplicitFragment _implicitFragment = new ImplicitFragment();
|
||||
fragments.add(_implicitFragment);
|
||||
return fragments;
|
||||
}
|
||||
|
||||
public void initialize(final Grammar grammar) {
|
||||
this.grammar = grammar;
|
||||
this.ruleNames = RuleNames.getRuleNames(grammar, true);
|
||||
}
|
||||
|
||||
private void installIndex() {
|
||||
List<IResourceDescription> _emptyList = Collections.<IResourceDescription>emptyList();
|
||||
final ResourceDescriptionsData index = new ResourceDescriptionsData(_emptyList);
|
||||
final ArrayList<Resource> resources = Lists.<Resource>newArrayList(this.resourceSet.getResources());
|
||||
for (final Resource resource : resources) {
|
||||
this.index(resource, resource.getURI(), index);
|
||||
}
|
||||
ResourceDescriptionsData.ResourceSetAdapter.installResourceDescriptionsData(this.resourceSet, index);
|
||||
}
|
||||
|
||||
private void index(final Resource resource, final URI uri, final ResourceDescriptionsData index) {
|
||||
final IResourceServiceProvider serviceProvider = IResourceServiceProvider.Registry.INSTANCE.getResourceServiceProvider(uri);
|
||||
if ((serviceProvider != null)) {
|
||||
final IResourceDescription resourceDescription = serviceProvider.getResourceDescriptionManager().getResourceDescription(resource);
|
||||
if ((resourceDescription != null)) {
|
||||
index.addDescription(uri, resourceDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateGrammar(final Grammar grammar) {
|
||||
this.validateAllImports(grammar);
|
||||
final EValidator validator = EValidator.Registry.INSTANCE.getEValidator(XtextPackage.eINSTANCE);
|
||||
if ((validator != null)) {
|
||||
final DiagnosticChain chain = new DiagnosticChain() {
|
||||
@Override
|
||||
public void add(final Diagnostic diagnostic) {
|
||||
int _severity = diagnostic.getSeverity();
|
||||
boolean _equals = (_severity == Diagnostic.ERROR);
|
||||
if (_equals) {
|
||||
String _name = grammar.getName();
|
||||
String _plus = ("Validation Error in " + _name);
|
||||
final String grammarName = (_plus + ": ");
|
||||
Throwable _exception = diagnostic.getException();
|
||||
boolean _tripleEquals = (_exception == null);
|
||||
if (_tripleEquals) {
|
||||
String _message = diagnostic.getMessage();
|
||||
String _plus_1 = (grammarName + _message);
|
||||
throw new IllegalStateException(_plus_1);
|
||||
} else {
|
||||
String _message_1 = diagnostic.getMessage();
|
||||
String _plus_2 = (grammarName + _message_1);
|
||||
Throwable _exception_1 = diagnostic.getException();
|
||||
throw new IllegalStateException(_plus_2, _exception_1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAll(final Diagnostic diagnostic) {
|
||||
this.add(diagnostic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void merge(final Diagnostic diagnostic) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
validator.validate(grammar, chain, null);
|
||||
final TreeIterator<EObject> iterator = grammar.eAllContents();
|
||||
while (iterator.hasNext()) {
|
||||
EObject _next = iterator.next();
|
||||
HashMap<Object, Object> _hashMap = new HashMap<Object, Object>();
|
||||
validator.validate(_next, chain, _hashMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateAllImports(final Grammar grammar) {
|
||||
List<AbstractMetamodelDeclaration> _allMetamodelDeclarations = GrammarUtil.allMetamodelDeclarations(grammar);
|
||||
for (final AbstractMetamodelDeclaration amd : _allMetamodelDeclarations) {
|
||||
if ((amd instanceof ReferencedMetamodel)) {
|
||||
this.validateReferencedMetamodel(((ReferencedMetamodel)amd));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateReferencedMetamodel(final ReferencedMetamodel ref) {
|
||||
if (((ref.getEPackage() != null) && (!ref.getEPackage().eIsProxy()))) {
|
||||
return;
|
||||
}
|
||||
final EReference eref = XtextPackage.Literals.ABSTRACT_METAMODEL_DECLARATION__EPACKAGE;
|
||||
final List<INode> nodes = NodeModelUtils.findNodesForFeature(ref, eref);
|
||||
String _xifexpression = null;
|
||||
boolean _isEmpty = nodes.isEmpty();
|
||||
if (_isEmpty) {
|
||||
_xifexpression = "(unknown)";
|
||||
} else {
|
||||
_xifexpression = NodeModelUtils.getTokenText(nodes.get(0));
|
||||
}
|
||||
final String refName = _xifexpression;
|
||||
final String grammarName = GrammarUtil.getGrammar(ref).getName();
|
||||
final String msg = ((((("The EPackage " + refName) + " in grammar ") + grammarName) + " could not be found. ") + "You might want to register that EPackage in your workflow file.");
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
|
||||
@Pure
|
||||
@Override
|
||||
public Grammar getGrammar() {
|
||||
return this.grammar;
|
||||
}
|
||||
|
||||
@Pure
|
||||
public RuleNames getRuleNames() {
|
||||
return this.ruleNames;
|
||||
}
|
||||
|
||||
@Pure
|
||||
public List<String> getReferencedResources() {
|
||||
return this.referencedResources;
|
||||
}
|
||||
|
||||
@Pure
|
||||
@Override
|
||||
public ResourceSet getResourceSet() {
|
||||
return this.resourceSet;
|
||||
}
|
||||
|
||||
public void setResourceSet(final ResourceSet resourceSet) {
|
||||
this.resourceSet = resourceSet;
|
||||
}
|
||||
|
||||
@Pure
|
||||
public com.google.inject.Module getGuiceModule() {
|
||||
return this.guiceModule;
|
||||
}
|
||||
|
||||
public void setGuiceModule(final com.google.inject.Module guiceModule) {
|
||||
this.guiceModule = guiceModule;
|
||||
}
|
||||
|
||||
@Pure
|
||||
@Override
|
||||
public StandaloneSetupAccess getRuntimeGenSetup() {
|
||||
return this.runtimeGenSetup;
|
||||
}
|
||||
|
||||
@Pure
|
||||
@Override
|
||||
public GuiceModuleAccess getRuntimeGenModule() {
|
||||
return this.runtimeGenModule;
|
||||
}
|
||||
|
||||
@Pure
|
||||
@Override
|
||||
public GuiceModuleAccess getIdeGenModule() {
|
||||
return this.ideGenModule;
|
||||
}
|
||||
|
||||
@Pure
|
||||
@Override
|
||||
public GuiceModuleAccess getEclipsePluginGenModule() {
|
||||
return this.eclipsePluginGenModule;
|
||||
}
|
||||
|
||||
@Pure
|
||||
@Override
|
||||
public GuiceModuleAccess getWebGenModule() {
|
||||
return this.webGenModule;
|
||||
}
|
||||
}
|
|
@ -1,316 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2015, 2017 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.xtext.generator.model.project;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import org.eclipse.emf.mwe2.runtime.Mandatory;
|
||||
import org.eclipse.xtend.lib.annotations.Accessors;
|
||||
import org.eclipse.xtext.xbase.lib.Pure;
|
||||
import org.eclipse.xtext.xtext.generator.Issues;
|
||||
import org.eclipse.xtext.xtext.generator.model.ManifestAccess;
|
||||
import org.eclipse.xtext.xtext.generator.model.PluginXmlAccess;
|
||||
import org.eclipse.xtext.xtext.generator.model.project.BundleProjectConfig;
|
||||
import org.eclipse.xtext.xtext.generator.model.project.RuntimeProjectConfig;
|
||||
import org.eclipse.xtext.xtext.generator.model.project.SubProjectConfig;
|
||||
import org.eclipse.xtext.xtext.generator.model.project.WebProjectConfig;
|
||||
import org.eclipse.xtext.xtext.generator.model.project.XtextProjectConfig;
|
||||
|
||||
/**
|
||||
* Specialized project configuration that uses standard names and paths. Usually it is sufficient to
|
||||
* set the {@code baseName} and {@code rootPath} properties and to enable the required subprojects.
|
||||
*
|
||||
* @noextend This class should not be extended by clients.
|
||||
*/
|
||||
@Accessors
|
||||
@SuppressWarnings("all")
|
||||
public class StandardProjectConfig extends XtextProjectConfig {
|
||||
/**
|
||||
* set to {@code true} by the project wizard(s) in case "Maven/Gradle" source layout is selected.
|
||||
*/
|
||||
private boolean mavenLayout;
|
||||
|
||||
private boolean createEclipseMetaData;
|
||||
|
||||
private String rootPath;
|
||||
|
||||
private String baseName;
|
||||
|
||||
/**
|
||||
* The base name of the project, which is usually equal to the runtime subproject.
|
||||
*/
|
||||
@Mandatory
|
||||
public String setBaseName(final String baseName) {
|
||||
return this.baseName = baseName;
|
||||
}
|
||||
|
||||
/**
|
||||
* The root path, usually {@code ".."}.
|
||||
*/
|
||||
@Mandatory
|
||||
public String setRootPath(final String rootPath) {
|
||||
return this.rootPath = rootPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkConfiguration(final Issues issues) {
|
||||
super.checkConfiguration(issues);
|
||||
if ((this.rootPath == null)) {
|
||||
issues.addError("The property \'rootPath\' must be set", this);
|
||||
}
|
||||
if ((this.baseName == null)) {
|
||||
issues.addError("The property \'baseName\' must be set", this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaults() {
|
||||
super.setDefaults();
|
||||
final Consumer<SubProjectConfig> _function = (SubProjectConfig it) -> {
|
||||
String _name = it.getName();
|
||||
boolean _tripleEquals = (_name == null);
|
||||
if (_tripleEquals) {
|
||||
it.setName(this.computeName(it));
|
||||
}
|
||||
String _rootPath = it.getRootPath();
|
||||
boolean _tripleEquals_1 = (_rootPath == null);
|
||||
if (_tripleEquals_1) {
|
||||
it.setRoot(this.computeRoot(it));
|
||||
}
|
||||
String _metaInfPath = it.getMetaInfPath();
|
||||
boolean _tripleEquals_2 = (_metaInfPath == null);
|
||||
if (_tripleEquals_2) {
|
||||
it.setMetaInf(this.computeMetaInf(it));
|
||||
}
|
||||
String _srcPath = it.getSrcPath();
|
||||
boolean _tripleEquals_3 = (_srcPath == null);
|
||||
if (_tripleEquals_3) {
|
||||
it.setSrc(this.computeSrc(it));
|
||||
}
|
||||
String _srcGenPath = it.getSrcGenPath();
|
||||
boolean _tripleEquals_4 = (_srcGenPath == null);
|
||||
if (_tripleEquals_4) {
|
||||
it.setSrcGen(this.computeSrcGen(it));
|
||||
}
|
||||
String _iconsPath = it.getIconsPath();
|
||||
boolean _tripleEquals_5 = (_iconsPath == null);
|
||||
if (_tripleEquals_5) {
|
||||
it.setIcons(this.computeIcons(it));
|
||||
}
|
||||
if ((it instanceof BundleProjectConfig)) {
|
||||
if (this.createEclipseMetaData) {
|
||||
ManifestAccess _manifest = ((BundleProjectConfig)it).getManifest();
|
||||
boolean _tripleEquals_6 = (_manifest == null);
|
||||
if (_tripleEquals_6) {
|
||||
((BundleProjectConfig)it).setManifest(this.newManifestAccess());
|
||||
}
|
||||
PluginXmlAccess _pluginXml = ((BundleProjectConfig)it).getPluginXml();
|
||||
boolean _tripleEquals_7 = (_pluginXml == null);
|
||||
if (_tripleEquals_7) {
|
||||
((BundleProjectConfig)it).setPluginXml(this.newPluginXmlAccess());
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((it instanceof RuntimeProjectConfig)) {
|
||||
String _ecoreModelPath = ((RuntimeProjectConfig)it).getEcoreModelPath();
|
||||
boolean _tripleEquals_8 = (_ecoreModelPath == null);
|
||||
if (_tripleEquals_8) {
|
||||
((RuntimeProjectConfig)it).setEcoreModel(this.computeEcoreModel(((RuntimeProjectConfig)it)));
|
||||
}
|
||||
}
|
||||
if ((it instanceof WebProjectConfig)) {
|
||||
String _assetsPath = ((WebProjectConfig)it).getAssetsPath();
|
||||
boolean _tripleEquals_9 = (_assetsPath == null);
|
||||
if (_tripleEquals_9) {
|
||||
((WebProjectConfig)it).setAssets(this.computeAssets(((WebProjectConfig)it)));
|
||||
}
|
||||
}
|
||||
};
|
||||
this.getEnabledProjects().forEach(_function);
|
||||
}
|
||||
|
||||
protected String computeName(final SubProjectConfig project) {
|
||||
String _switchResult = null;
|
||||
boolean _matched = false;
|
||||
RuntimeProjectConfig _runtime = this.getRuntime();
|
||||
if (Objects.equal(project, _runtime)) {
|
||||
_matched=true;
|
||||
_switchResult = this.baseName;
|
||||
}
|
||||
if (!_matched) {
|
||||
BundleProjectConfig _runtimeTest = this.getRuntimeTest();
|
||||
if (Objects.equal(project, _runtimeTest)) {
|
||||
_matched=true;
|
||||
String _xifexpression = null;
|
||||
if ((!this.mavenLayout)) {
|
||||
_xifexpression = (this.baseName + ".tests");
|
||||
} else {
|
||||
_xifexpression = this.baseName;
|
||||
}
|
||||
_switchResult = _xifexpression;
|
||||
}
|
||||
}
|
||||
if (!_matched) {
|
||||
BundleProjectConfig _genericIde = this.getGenericIde();
|
||||
if (Objects.equal(project, _genericIde)) {
|
||||
_matched=true;
|
||||
_switchResult = (this.baseName + ".ide");
|
||||
}
|
||||
}
|
||||
if (!_matched) {
|
||||
BundleProjectConfig _eclipsePlugin = this.getEclipsePlugin();
|
||||
if (Objects.equal(project, _eclipsePlugin)) {
|
||||
_matched=true;
|
||||
_switchResult = (this.baseName + ".ui");
|
||||
}
|
||||
}
|
||||
if (!_matched) {
|
||||
BundleProjectConfig _eclipsePluginTest = this.getEclipsePluginTest();
|
||||
if (Objects.equal(project, _eclipsePluginTest)) {
|
||||
_matched=true;
|
||||
String _xifexpression_1 = null;
|
||||
if ((!this.mavenLayout)) {
|
||||
_xifexpression_1 = (this.baseName + ".ui.tests");
|
||||
} else {
|
||||
_xifexpression_1 = (this.baseName + ".ui");
|
||||
}
|
||||
_switchResult = _xifexpression_1;
|
||||
}
|
||||
}
|
||||
if (!_matched) {
|
||||
WebProjectConfig _web = this.getWeb();
|
||||
if (Objects.equal(project, _web)) {
|
||||
_matched=true;
|
||||
_switchResult = (this.baseName + ".web");
|
||||
}
|
||||
}
|
||||
return _switchResult;
|
||||
}
|
||||
|
||||
protected String computeRoot(final SubProjectConfig project) {
|
||||
String _name = project.getName();
|
||||
return ((this.rootPath + "/") + _name);
|
||||
}
|
||||
|
||||
/**
|
||||
* In case of "Maven/Gradle" source layout the src outlet is named 'src/main/java',
|
||||
* test classes go into 'src/test/java' instead of any dedicated '...tests' project.
|
||||
*/
|
||||
protected String computeSrc(final SubProjectConfig project) {
|
||||
String _rootPath = project.getRootPath();
|
||||
String _plus = (_rootPath + "/");
|
||||
String _xifexpression = null;
|
||||
if (this.mavenLayout) {
|
||||
String _computeSourceSet = this.computeSourceSet(project);
|
||||
String _plus_1 = ("src/" + _computeSourceSet);
|
||||
_xifexpression = (_plus_1 + "/java");
|
||||
} else {
|
||||
_xifexpression = "src";
|
||||
}
|
||||
return (_plus + _xifexpression);
|
||||
}
|
||||
|
||||
/**
|
||||
* In case of "Maven/Gradle" source layout the srcGen outlet is named 'src/main/xtext-gen',
|
||||
* test-related srcGen classes go into 'src/test/xtext-gen' instead of any dedicated '...tests' project.
|
||||
* Don't confuse it with 'src/main/xtend-gen'!
|
||||
*/
|
||||
protected String computeSrcGen(final SubProjectConfig project) {
|
||||
String _rootPath = project.getRootPath();
|
||||
String _plus = (_rootPath + "/");
|
||||
String _xifexpression = null;
|
||||
if (this.mavenLayout) {
|
||||
String _computeSourceSet = this.computeSourceSet(project);
|
||||
String _plus_1 = ("src/" + _computeSourceSet);
|
||||
_xifexpression = (_plus_1 + "/xtext-gen");
|
||||
} else {
|
||||
_xifexpression = "src-gen";
|
||||
}
|
||||
return (_plus + _xifexpression);
|
||||
}
|
||||
|
||||
protected String computeMetaInf(final SubProjectConfig project) {
|
||||
String _rootPath = project.getRootPath();
|
||||
String _plus = (_rootPath + "/");
|
||||
String _xifexpression = null;
|
||||
if (this.mavenLayout) {
|
||||
String _computeSourceSet = this.computeSourceSet(project);
|
||||
String _plus_1 = ("src/" + _computeSourceSet);
|
||||
_xifexpression = (_plus_1 + "/resources/META-INF");
|
||||
} else {
|
||||
_xifexpression = "META-INF";
|
||||
}
|
||||
return (_plus + _xifexpression);
|
||||
}
|
||||
|
||||
protected String computeEcoreModel(final RuntimeProjectConfig project) {
|
||||
String _rootPath = project.getRootPath();
|
||||
String _plus = (_rootPath + "/");
|
||||
return (_plus + "model/generated");
|
||||
}
|
||||
|
||||
protected String computeAssets(final WebProjectConfig project) {
|
||||
String _rootPath = project.getRootPath();
|
||||
String _plus = (_rootPath + "/");
|
||||
String _xifexpression = null;
|
||||
if (this.mavenLayout) {
|
||||
String _computeSourceSet = this.computeSourceSet(project);
|
||||
String _plus_1 = ("src/" + _computeSourceSet);
|
||||
_xifexpression = (_plus_1 + "/webapp");
|
||||
} else {
|
||||
_xifexpression = "WebRoot";
|
||||
}
|
||||
return (_plus + _xifexpression);
|
||||
}
|
||||
|
||||
protected String computeSourceSet(final SubProjectConfig project) {
|
||||
String _xifexpression = null;
|
||||
boolean _contains = this.getTestProjects().contains(project);
|
||||
if (_contains) {
|
||||
_xifexpression = "test";
|
||||
} else {
|
||||
_xifexpression = "main";
|
||||
}
|
||||
return _xifexpression;
|
||||
}
|
||||
|
||||
protected String computeIcons(final SubProjectConfig project) {
|
||||
String _rootPath = project.getRootPath();
|
||||
String _plus = (_rootPath + "/");
|
||||
return (_plus + "icons");
|
||||
}
|
||||
|
||||
@Pure
|
||||
public boolean isMavenLayout() {
|
||||
return this.mavenLayout;
|
||||
}
|
||||
|
||||
public void setMavenLayout(final boolean mavenLayout) {
|
||||
this.mavenLayout = mavenLayout;
|
||||
}
|
||||
|
||||
@Pure
|
||||
public boolean isCreateEclipseMetaData() {
|
||||
return this.createEclipseMetaData;
|
||||
}
|
||||
|
||||
public void setCreateEclipseMetaData(final boolean createEclipseMetaData) {
|
||||
this.createEclipseMetaData = createEclipseMetaData;
|
||||
}
|
||||
|
||||
@Pure
|
||||
public String getRootPath() {
|
||||
return this.rootPath;
|
||||
}
|
||||
|
||||
@Pure
|
||||
public String getBaseName() {
|
||||
return this.baseName;
|
||||
}
|
||||
}
|
|
@ -1,358 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2015 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.xtext.generator.parser.antlr;
|
||||
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.inject.Inject;
|
||||
import java.io.CharArrayWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import org.eclipse.xtend.lib.annotations.AccessorType;
|
||||
import org.eclipse.xtend.lib.annotations.Accessors;
|
||||
import org.eclipse.xtext.AbstractRule;
|
||||
import org.eclipse.xtext.Grammar;
|
||||
import org.eclipse.xtext.GrammarUtil;
|
||||
import org.eclipse.xtext.ParserRule;
|
||||
import org.eclipse.xtext.UnorderedGroup;
|
||||
import org.eclipse.xtext.generator.LineSeparatorHarmonizer;
|
||||
import org.eclipse.xtext.parser.antlr.IAntlrTokenFileProvider;
|
||||
import org.eclipse.xtext.util.Strings;
|
||||
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.Pure;
|
||||
import org.eclipse.xtext.xtext.generator.AbstractXtextGeneratorFragment;
|
||||
import org.eclipse.xtext.xtext.generator.CodeConfig;
|
||||
import org.eclipse.xtext.xtext.generator.Issues;
|
||||
import org.eclipse.xtext.xtext.generator.model.IXtextGeneratorFileSystemAccess;
|
||||
import org.eclipse.xtext.xtext.generator.model.TypeReference;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.AntlrGrammar;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.AntlrGrammarGenUtil;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.AntlrOptions;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.AntlrToolFacade;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.KeywordHelper;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.MutableTokenDefProvider;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.postProcessing.SuppressWarningsProcessor;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.AntlrCodeQualityHelper;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.AntlrLexerSplitter;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.AntlrParserSplitter;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.BacktrackingGuardForUnorderedGroupsRemover;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.BacktrackingGuardRemover;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.PartialClassExtractor;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.SyntacticPredicateFixup;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.splitting.UnorderedGroupsSplitter;
|
||||
|
||||
@SuppressWarnings("all")
|
||||
public abstract class AbstractAntlrGeneratorFragment2 extends AbstractXtextGeneratorFragment {
|
||||
@Inject
|
||||
@Accessors(AccessorType.PROTECTED_GETTER)
|
||||
private AntlrToolFacade antlrTool;
|
||||
|
||||
@Inject
|
||||
@Accessors(AccessorType.PROTECTED_GETTER)
|
||||
private AntlrCodeQualityHelper codeQualityHelper;
|
||||
|
||||
@Inject
|
||||
@Accessors(AccessorType.PROTECTED_GETTER)
|
||||
private LineSeparatorHarmonizer newLineNormalizer;
|
||||
|
||||
@Inject
|
||||
@Accessors(AccessorType.PROTECTED_GETTER)
|
||||
private CodeConfig codeConfig;
|
||||
|
||||
@Accessors
|
||||
private AntlrOptions options = new AntlrOptions();
|
||||
|
||||
private final ArrayList<String> antlrParams = CollectionLiterals.<String>newArrayList();
|
||||
|
||||
public void addAntlrParam(final String param) {
|
||||
this.antlrParams.add(param);
|
||||
}
|
||||
|
||||
public String[] getAntlrParams() {
|
||||
ArrayList<String> params = Lists.<String>newArrayList(this.antlrParams);
|
||||
boolean _contains = params.contains("-Xconversiontimeout");
|
||||
boolean _not = (!_contains);
|
||||
if (_not) {
|
||||
params.add(0, "-Xconversiontimeout");
|
||||
params.add(1, "100000");
|
||||
}
|
||||
return ((String[])Conversions.unwrapArray(params, String.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkConfiguration(final Issues issues) {
|
||||
super.checkConfiguration(issues);
|
||||
boolean _isWorkable = this.antlrTool.isWorkable();
|
||||
boolean _not = (!_isWorkable);
|
||||
if (_not) {
|
||||
issues.addError("\n\n*ATTENTION*\nIt is highly recommended to use ANTLR\'s parser generator (get it from \'http://xtext.itemis.com/\'). \nAs an alternative to ANTLR you could also use the alternative implementation shipped with Xtext.\nTo do so use the generator fragment \'org.eclipse.xtext.generator.parser.packrat.PackratParserFragment\' in your mwe2 file instead.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate() {
|
||||
this.checkGrammar();
|
||||
this.doGenerate();
|
||||
}
|
||||
|
||||
protected abstract void doGenerate();
|
||||
|
||||
protected void checkGrammar() {
|
||||
boolean _hasProductionRules = this.hasProductionRules(this.getGrammar());
|
||||
boolean _not = (!_hasProductionRules);
|
||||
if (_not) {
|
||||
throw new IllegalArgumentException("You may not generate an ANTLR parser for a grammar without production rules.");
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean hasProductionRules(final Grammar grammar) {
|
||||
AbstractRule firstRule = grammar.getRules().get(0);
|
||||
return ((firstRule instanceof ParserRule) && (!GrammarUtil.isDatatypeRule(((ParserRule) firstRule))));
|
||||
}
|
||||
|
||||
protected void splitLexerClassFile(final IXtextGeneratorFileSystemAccess fsa, final TypeReference lexer) {
|
||||
final String content = fsa.readTextFile(lexer.getJavaPath()).toString();
|
||||
AntlrLexerSplitter splitter = new AntlrLexerSplitter(content);
|
||||
splitter.setCasesPerSpecialStateSwitch(this.options.getCasesPerSpecialStateSwitch());
|
||||
fsa.generateFile(lexer.getJavaPath(), splitter.transform());
|
||||
}
|
||||
|
||||
protected void splitParserClassFile(final IXtextGeneratorFileSystemAccess fsa, final TypeReference parser) {
|
||||
final String content = fsa.readTextFile(parser.getJavaPath()).toString();
|
||||
int _fieldsPerClass = this.getOptions().getFieldsPerClass();
|
||||
final AntlrParserSplitter splitter = new AntlrParserSplitter(content, _fieldsPerClass);
|
||||
String _transform = splitter.transform();
|
||||
int _methodsPerClass = this.getOptions().getMethodsPerClass();
|
||||
final PartialClassExtractor extractor = new PartialClassExtractor(_transform, _methodsPerClass);
|
||||
fsa.generateFile(parser.getJavaPath(), extractor.transform());
|
||||
}
|
||||
|
||||
protected void simplifyUnorderedGroupPredicatesIfRequired(final Grammar grammar, final IXtextGeneratorFileSystemAccess fsa, final TypeReference parser) {
|
||||
if ((this.containsUnorderedGroup(grammar) || this.hasParameterizedRules(grammar))) {
|
||||
this.simplifyUnorderedGroupPredicates(fsa, parser);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean hasParameterizedRules(final Grammar grammar) {
|
||||
List<ParserRule> _allParserRules = GrammarUtil.allParserRules(grammar);
|
||||
for (final ParserRule rule : _allParserRules) {
|
||||
boolean _isEmpty = rule.getParameters().isEmpty();
|
||||
boolean _not = (!_isEmpty);
|
||||
if (_not) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void simplifyUnorderedGroupPredicates(final IXtextGeneratorFileSystemAccess fsa, final TypeReference parser) {
|
||||
final String content = fsa.readTextFile(parser.getJavaPath()).toString();
|
||||
UnorderedGroupsSplitter splitter = new UnorderedGroupsSplitter(content);
|
||||
String transformed = splitter.transform();
|
||||
SyntacticPredicateFixup fixup = new SyntacticPredicateFixup(transformed);
|
||||
transformed = fixup.transform();
|
||||
BacktrackingGuardForUnorderedGroupsRemover remover = new BacktrackingGuardForUnorderedGroupsRemover(transformed);
|
||||
String newContent = remover.transform();
|
||||
fsa.generateFile(parser.getJavaPath(), newContent);
|
||||
}
|
||||
|
||||
protected void suppressWarnings(final IXtextGeneratorFileSystemAccess fsa, final TypeReference type) {
|
||||
final String content = fsa.readTextFile(type.getJavaPath()).toString();
|
||||
final String newContent = new SuppressWarningsProcessor().process(content);
|
||||
fsa.generateFile(type.getJavaPath(), newContent);
|
||||
}
|
||||
|
||||
protected void suppressWarnings(final IXtextGeneratorFileSystemAccess fsa, final TypeReference... types) {
|
||||
final Consumer<TypeReference> _function = (TypeReference it) -> {
|
||||
this.suppressWarnings(fsa, it);
|
||||
};
|
||||
((List<TypeReference>)Conversions.doWrapArray(types)).forEach(_function);
|
||||
}
|
||||
|
||||
protected void normalizeLineDelimiters(final IXtextGeneratorFileSystemAccess fsa, final TypeReference type) {
|
||||
String content = fsa.readTextFile(type.getJavaPath()).toString();
|
||||
content = this.newLineNormalizer.postProcess(fsa.getURI(type.getJavaPath()), content).toString();
|
||||
content = content.replaceAll("\"\\+(\\r)?\\n\\s+\"", "");
|
||||
fsa.generateFile(type.getJavaPath(), content);
|
||||
}
|
||||
|
||||
protected void normalizeLineDelimiters(final IXtextGeneratorFileSystemAccess fsa, final TypeReference... types) {
|
||||
final Consumer<TypeReference> _function = (TypeReference it) -> {
|
||||
this.normalizeLineDelimiters(fsa, it);
|
||||
};
|
||||
((List<TypeReference>)Conversions.doWrapArray(types)).forEach(_function);
|
||||
}
|
||||
|
||||
protected void normalizeTokens(final IXtextGeneratorFileSystemAccess fsa, final String tokenFile) {
|
||||
String content = fsa.readTextFile(tokenFile).toString();
|
||||
content = this.newLineNormalizer.postProcess(fsa.getURI(tokenFile), content).toString();
|
||||
final List<String> splitted = Strings.split(content, this.codeConfig.getLineDelimiter());
|
||||
Collections.<String>sort(splitted);
|
||||
String _concat = Strings.concat(this.codeConfig.getLineDelimiter(), splitted);
|
||||
String _lineDelimiter = this.codeConfig.getLineDelimiter();
|
||||
String _plus = (_concat + _lineDelimiter);
|
||||
content = _plus;
|
||||
fsa.generateFile(tokenFile, content);
|
||||
}
|
||||
|
||||
protected void splitParserAndLexerIfEnabled(final IXtextGeneratorFileSystemAccess fsa, final TypeReference parser, final TypeReference lexer) {
|
||||
this.improveCodeQuality(fsa, lexer, parser);
|
||||
boolean _isClassSplitting = this.getOptions().isClassSplitting();
|
||||
if (_isClassSplitting) {
|
||||
this.splitLexerClassFile(fsa, lexer);
|
||||
this.splitParserClassFile(fsa, parser);
|
||||
}
|
||||
}
|
||||
|
||||
protected void improveCodeQuality(final IXtextGeneratorFileSystemAccess fsa, final TypeReference lexer, final TypeReference parser) {
|
||||
this.improveLexerCodeQuality(fsa, lexer);
|
||||
this.improveParserCodeQuality(fsa, parser);
|
||||
}
|
||||
|
||||
protected void improveParserCodeQuality(final IXtextGeneratorFileSystemAccess fsa, final TypeReference parser) {
|
||||
String parserContent = fsa.readTextFile(parser.getJavaPath()).toString();
|
||||
parserContent = this.codeQualityHelper.stripUnnecessaryComments(parserContent, this.options);
|
||||
parserContent = this.codeQualityHelper.removeDuplicateBitsets(parserContent, this.options);
|
||||
parserContent = this.codeQualityHelper.removeDuplicateDFAs(parserContent, this.options);
|
||||
fsa.generateFile(parser.getJavaPath(), parserContent);
|
||||
}
|
||||
|
||||
protected void improveLexerCodeQuality(final IXtextGeneratorFileSystemAccess fsa, final TypeReference lexer) {
|
||||
String lexerContent = fsa.readTextFile(lexer.getJavaPath()).toString();
|
||||
lexerContent = this.codeQualityHelper.stripUnnecessaryComments(lexerContent, this.options);
|
||||
fsa.generateFile(lexer.getJavaPath(), lexerContent);
|
||||
}
|
||||
|
||||
protected void cleanupLexerTokensFile(final AntlrGrammar lexerGrammar, final KeywordHelper helper, final IXtextGeneratorFileSystemAccess fsa) {
|
||||
try {
|
||||
boolean _isBacktrackLexer = this.options.isBacktrackLexer();
|
||||
if (_isBacktrackLexer) {
|
||||
final MutableTokenDefProvider provider = this.createLexerTokensProvider(lexerGrammar, helper, fsa);
|
||||
final Iterator<Map.Entry<Integer, String>> entries = provider.getTokenDefMap().entrySet().iterator();
|
||||
while (entries.hasNext()) {
|
||||
{
|
||||
final String value = entries.next().getValue();
|
||||
if ((((!helper.isKeywordRule(value)) && (!value.startsWith("RULE_"))) && (!value.startsWith("SUPER_")))) {
|
||||
entries.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
final CharArrayWriter writer = new CharArrayWriter();
|
||||
PrintWriter _printWriter = new PrintWriter(writer);
|
||||
provider.writeTokenFile(_printWriter);
|
||||
String _tokensFileName = lexerGrammar.getTokensFileName();
|
||||
char[] _charArray = writer.toCharArray();
|
||||
String _string = new String(_charArray);
|
||||
fsa.generateFile(_tokensFileName, _string);
|
||||
}
|
||||
} catch (Throwable _e) {
|
||||
throw Exceptions.sneakyThrow(_e);
|
||||
}
|
||||
}
|
||||
|
||||
protected MutableTokenDefProvider createLexerTokensProvider(final AntlrGrammar lexerGrammar, final KeywordHelper helper, final IXtextGeneratorFileSystemAccess fsa) {
|
||||
Charset _forName = Charset.forName(this.codeConfig.getEncoding());
|
||||
final MutableTokenDefProvider provider = new MutableTokenDefProvider(helper, _forName);
|
||||
final IAntlrTokenFileProvider _function = () -> {
|
||||
return fsa.readBinaryFile(lexerGrammar.getTokensFileName());
|
||||
};
|
||||
provider.setAntlrTokenFileProvider(_function);
|
||||
return provider;
|
||||
}
|
||||
|
||||
protected void cleanupParserTokensFile(final AntlrGrammar lexerGrammar, final AntlrGrammar parserGrammar, final KeywordHelper helper, final IXtextGeneratorFileSystemAccess fsa) {
|
||||
try {
|
||||
final MutableTokenDefProvider provider = this.createLexerTokensProvider(lexerGrammar, helper, fsa);
|
||||
Set<Map.Entry<Integer, String>> _entrySet = provider.getTokenDefMap().entrySet();
|
||||
for (final Map.Entry<Integer, String> entry : _entrySet) {
|
||||
{
|
||||
final String value = entry.getValue();
|
||||
boolean _isKeywordRule = helper.isKeywordRule(value);
|
||||
if (_isKeywordRule) {
|
||||
final String keywordAsAntlrString = AntlrGrammarGenUtil.toAntlrString(helper.getKeywordValue(value));
|
||||
entry.setValue((("\'" + keywordAsAntlrString) + "\'"));
|
||||
} else {
|
||||
boolean _startsWith = value.startsWith("\'");
|
||||
if (_startsWith) {
|
||||
String _antlrString = AntlrGrammarGenUtil.toAntlrString(value);
|
||||
String _plus = ("\'" + _antlrString);
|
||||
String _plus_1 = (_plus + "\'");
|
||||
entry.setValue(_plus_1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
final CharArrayWriter writer = new CharArrayWriter();
|
||||
PrintWriter _printWriter = new PrintWriter(writer);
|
||||
provider.writeTokenFile(_printWriter);
|
||||
String _tokensFileName = parserGrammar.getTokensFileName();
|
||||
char[] _charArray = writer.toCharArray();
|
||||
String _string = new String(_charArray);
|
||||
fsa.generateFile(_tokensFileName, _string);
|
||||
} catch (Throwable _e) {
|
||||
throw Exceptions.sneakyThrow(_e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void removeBackTrackingGuards(final IXtextGeneratorFileSystemAccess fsa, final TypeReference parser, final int lookaheadThreshold) {
|
||||
final String content = fsa.readTextFile(parser.getJavaPath()).toString();
|
||||
final BacktrackingGuardRemover remover = new BacktrackingGuardRemover(content, lookaheadThreshold);
|
||||
final String newContent = remover.transform();
|
||||
fsa.generateFile(parser.getJavaPath(), newContent);
|
||||
}
|
||||
|
||||
protected boolean containsUnorderedGroup(final Grammar grammar) {
|
||||
List<ParserRule> _allParserRules = GrammarUtil.allParserRules(grammar);
|
||||
for (final ParserRule rule : _allParserRules) {
|
||||
boolean _hasNext = Iterators.<UnorderedGroup>filter(rule.eAllContents(), UnorderedGroup.class).hasNext();
|
||||
if (_hasNext) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Pure
|
||||
protected AntlrToolFacade getAntlrTool() {
|
||||
return this.antlrTool;
|
||||
}
|
||||
|
||||
@Pure
|
||||
protected AntlrCodeQualityHelper getCodeQualityHelper() {
|
||||
return this.codeQualityHelper;
|
||||
}
|
||||
|
||||
@Pure
|
||||
protected LineSeparatorHarmonizer getNewLineNormalizer() {
|
||||
return this.newLineNormalizer;
|
||||
}
|
||||
|
||||
@Pure
|
||||
protected CodeConfig getCodeConfig() {
|
||||
return this.codeConfig;
|
||||
}
|
||||
|
||||
@Pure
|
||||
public AntlrOptions getOptions() {
|
||||
return this.options;
|
||||
}
|
||||
|
||||
public void setOptions(final AntlrOptions options) {
|
||||
this.options = options;
|
||||
}
|
||||
}
|
|
@ -1,153 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2015 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.xtext.xtext.generator.parser.antlr;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import org.eclipse.xtend2.lib.StringConcatenation;
|
||||
import org.eclipse.xtext.Grammar;
|
||||
import org.eclipse.xtext.GrammarUtil;
|
||||
import org.eclipse.xtext.xbase.lib.Extension;
|
||||
import org.eclipse.xtext.xtext.generator.XtextGeneratorNaming;
|
||||
import org.eclipse.xtext.xtext.generator.model.TypeReference;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.AntlrGrammar;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.CombinedGrammarMarker;
|
||||
|
||||
@Singleton
|
||||
@SuppressWarnings("all")
|
||||
public class GrammarNaming {
|
||||
@Inject
|
||||
@Extension
|
||||
private XtextGeneratorNaming _xtextGeneratorNaming;
|
||||
|
||||
public boolean isCombinedGrammar(final Grammar it) {
|
||||
return CombinedGrammarMarker.findInEmfObject(it).isCombinedGrammar();
|
||||
}
|
||||
|
||||
protected String getParserPackage(final Grammar it) {
|
||||
String _runtimeBasePackage = this._xtextGeneratorNaming.getRuntimeBasePackage(it);
|
||||
return (_runtimeBasePackage + ".parser.antlr");
|
||||
}
|
||||
|
||||
protected String getInternalParserPackage(final Grammar it) {
|
||||
String _parserPackage = this.getParserPackage(it);
|
||||
return (_parserPackage + ".internal");
|
||||
}
|
||||
|
||||
protected String getInternalLexerPackage(final Grammar it) {
|
||||
String _parserPackage = this.getParserPackage(it);
|
||||
return (_parserPackage + ".lexer");
|
||||
}
|
||||
|
||||
public AntlrGrammar getParserGrammar(final Grammar it) {
|
||||
String _internalParserPackage = this.getInternalParserPackage(it);
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
String _grammarNamePrefix = this.getGrammarNamePrefix(it);
|
||||
_builder.append(_grammarNamePrefix);
|
||||
_builder.append("Internal");
|
||||
String _simpleName = GrammarUtil.getSimpleName(it);
|
||||
_builder.append(_simpleName);
|
||||
{
|
||||
boolean _isCombinedGrammar = this.isCombinedGrammar(it);
|
||||
boolean _not = (!_isCombinedGrammar);
|
||||
if (_not) {
|
||||
_builder.append("Parser");
|
||||
}
|
||||
}
|
||||
return new AntlrGrammar(_internalParserPackage, _builder.toString());
|
||||
}
|
||||
|
||||
public AntlrGrammar getLexerGrammar(final Grammar it) {
|
||||
AntlrGrammar _xifexpression = null;
|
||||
boolean _isCombinedGrammar = this.isCombinedGrammar(it);
|
||||
if (_isCombinedGrammar) {
|
||||
_xifexpression = this.getParserGrammar(it);
|
||||
} else {
|
||||
String _internalLexerPackage = this.getInternalLexerPackage(it);
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
String _grammarNamePrefix = this.getGrammarNamePrefix(it);
|
||||
_builder.append(_grammarNamePrefix);
|
||||
_builder.append("Internal");
|
||||
String _simpleName = GrammarUtil.getSimpleName(it);
|
||||
_builder.append(_simpleName);
|
||||
_builder.append("Lexer");
|
||||
_xifexpression = new AntlrGrammar(_internalLexerPackage, _builder.toString());
|
||||
}
|
||||
return _xifexpression;
|
||||
}
|
||||
|
||||
protected String getGrammarNamePrefix(final Grammar it) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public TypeReference getLexerClass(final Grammar it) {
|
||||
String _packageName = this.getLexerGrammar(it).getPackageName();
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
String _simpleName = this.getLexerGrammar(it).getSimpleName();
|
||||
_builder.append(_simpleName);
|
||||
{
|
||||
boolean _isCombinedGrammar = this.isCombinedGrammar(it);
|
||||
if (_isCombinedGrammar) {
|
||||
_builder.append("Lexer");
|
||||
}
|
||||
}
|
||||
return new TypeReference(_packageName, _builder.toString());
|
||||
}
|
||||
|
||||
public TypeReference getLexerSuperClass(final Grammar it) {
|
||||
return new TypeReference("org.eclipse.xtext.parser.antlr.Lexer");
|
||||
}
|
||||
|
||||
public TypeReference getParserClass(final Grammar it) {
|
||||
String _parserPackage = this.getParserPackage(it);
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
String _simpleName = GrammarUtil.getSimpleName(it);
|
||||
_builder.append(_simpleName);
|
||||
_builder.append("Parser");
|
||||
return new TypeReference(_parserPackage, _builder.toString());
|
||||
}
|
||||
|
||||
public TypeReference getParserSuperClass(final Grammar it, final boolean partialParsing) {
|
||||
return new TypeReference("org.eclipse.xtext.parser.antlr.AbstractAntlrParser");
|
||||
}
|
||||
|
||||
public TypeReference getInternalParserClass(final Grammar it) {
|
||||
String _packageName = this.getParserGrammar(it).getPackageName();
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
String _simpleName = this.getParserGrammar(it).getSimpleName();
|
||||
_builder.append(_simpleName);
|
||||
{
|
||||
boolean _isCombinedGrammar = this.isCombinedGrammar(it);
|
||||
if (_isCombinedGrammar) {
|
||||
_builder.append("Parser");
|
||||
}
|
||||
}
|
||||
return new TypeReference(_packageName, _builder.toString());
|
||||
}
|
||||
|
||||
public TypeReference getInternalParserSuperClass(final Grammar it) {
|
||||
return new TypeReference("org.eclipse.xtext.parser.antlr.AbstractInternalAntlrParser");
|
||||
}
|
||||
|
||||
public TypeReference getAntlrTokenFileProviderClass(final Grammar it) {
|
||||
String _parserPackage = this.getParserPackage(it);
|
||||
StringConcatenation _builder = new StringConcatenation();
|
||||
String _simpleName = GrammarUtil.getSimpleName(it);
|
||||
_builder.append(_simpleName);
|
||||
_builder.append("AntlrTokenFileProvider");
|
||||
return new TypeReference(_parserPackage, _builder.toString());
|
||||
}
|
||||
|
||||
public TypeReference getTokenSourceClass(final Grammar it) {
|
||||
String _parserPackage = this.getParserPackage(it);
|
||||
String _simpleName = GrammarUtil.getSimpleName(it);
|
||||
String _plus = (_simpleName + "TokenSource");
|
||||
return new TypeReference(_parserPackage, _plus);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue