diff --git a/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/contentassist/ContentAssistService.java b/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/contentassist/ContentAssistService.java new file mode 100644 index 0000000000..8cdca7b761 --- /dev/null +++ b/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/contentassist/ContentAssistService.java @@ -0,0 +1,201 @@ +/** + * 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.server.contentassist; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.concurrent.ExecutorService; + +import org.eclipse.lsp4j.CompletionItem; +import org.eclipse.lsp4j.CompletionItemKind; +import org.eclipse.lsp4j.CompletionList; +import org.eclipse.lsp4j.CompletionParams; +import org.eclipse.lsp4j.InsertTextFormat; +import org.eclipse.lsp4j.Position; +import org.eclipse.lsp4j.Range; +import org.eclipse.lsp4j.TextEdit; +import org.eclipse.xtext.ide.editor.contentassist.ContentAssistContext; +import org.eclipse.xtext.ide.editor.contentassist.ContentAssistEntry; +import org.eclipse.xtext.ide.editor.contentassist.IIdeContentProposalAcceptor; +import org.eclipse.xtext.ide.editor.contentassist.IdeContentProposalAcceptor; +import org.eclipse.xtext.ide.editor.contentassist.IdeContentProposalProvider; +import org.eclipse.xtext.ide.editor.contentassist.antlr.ContentAssistContextFactory; +import org.eclipse.xtext.ide.server.Document; +import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.service.OperationCanceledManager; +import org.eclipse.xtext.util.CancelIndicator; +import org.eclipse.xtext.util.ReplaceRegion; +import org.eclipse.xtext.util.TextRegion; +import org.eclipse.xtext.xbase.lib.Exceptions; + +import com.google.common.base.Strings; +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; + +/** + * @author kosyakov - Initial contribution and API + * @author Dennis Huebner - additionalTextEdits support + * + * @since 2.11 + */ +@Singleton +public class ContentAssistService { + public final static int DEFAULT_PROPOSALS_LIMIT = 1000; + + @Inject + private Provider contextFactoryProvider; + + @Inject + private ExecutorService executorService; + + @Inject + private IdeContentProposalProvider proposalProvider; + + @Inject + private Provider proposalAcceptorProvider; + + @Inject + private OperationCanceledManager operationCanceledManager; + + public CompletionList createCompletionList(Document document, XtextResource resource, CompletionParams params, + CancelIndicator cancelIndicator) { + try { + CompletionList result = new CompletionList(); + result.setIsIncomplete(true); + IdeContentProposalAcceptor acceptor = proposalAcceptorProvider.get(); + int caretOffset = document.getOffSet(params.getPosition()); + Position caretPosition = params.getPosition(); + TextRegion position = new TextRegion(caretOffset, 0); + try { + createProposals(document.getContents(), position, caretOffset, resource, acceptor); + } catch (Throwable t) { + if (!operationCanceledManager.isOperationCanceledException(t)) { + throw t; + } + } + int idx = 0; + for (ContentAssistEntry it : acceptor.getEntries()) { + CompletionItem item = toCompletionItem(it, caretOffset, caretPosition, document); + item.setSortText(Strings.padStart(Integer.toString(idx), 5, '0')); + result.getItems().add(item); + idx++; + } + return result; + } catch (Throwable e) { + throw Exceptions.sneakyThrow(e); + } + } + + protected void createProposals(String document, TextRegion selection, int caretOffset, XtextResource resource, + IIdeContentProposalAcceptor acceptor) { + if (caretOffset > document.length()) { + return; + } + ContentAssistContextFactory contextFactory = contextFactoryProvider.get(); + contextFactory.setPool(executorService); + ContentAssistContext[] contexts = contextFactory.create(document, selection, caretOffset, resource); + proposalProvider.createProposals(Arrays.asList(contexts), acceptor); + } + + protected CompletionItem toCompletionItem(ContentAssistEntry entry, int caretOffset, Position caretPosition, + Document document) { + CompletionItem completionItem = new CompletionItem(); + String label = entry.getLabel(); + if (label == null) { + label = entry.getProposal(); + } + completionItem.setLabel(label); + completionItem.setDetail(entry.getDescription()); + completionItem.setDocumentation(entry.getDocumentation()); + String prefix = entry.getPrefix(); + if (prefix == null) { + prefix = ""; + } + int prefixOffset = caretOffset - prefix.length(); + Position prefixPosition = document.getPosition(prefixOffset); + completionItem.setTextEdit(new TextEdit(new Range(prefixPosition, caretPosition), entry.getProposal())); + completionItem.setKind(translateKind(entry)); + if (!entry.getTextReplacements().isEmpty()) { + if (completionItem.getAdditionalTextEdits() == null) { + completionItem.setAdditionalTextEdits(new ArrayList<>(entry.getTextReplacements().size())); + } + entry.getTextReplacements().forEach( + (ReplaceRegion it) -> completionItem.getAdditionalTextEdits().add(toTextEdit(it, document))); + } + if (ContentAssistEntry.KIND_SNIPPET.equals(entry.getKind())) { + completionItem.setInsertTextFormat(InsertTextFormat.Snippet); + } + return completionItem; + } + + protected CompletionItemKind translateKind(ContentAssistEntry entry) { + if (entry.getKind() != null) { + switch (entry.getKind()) { + case ContentAssistEntry.KIND_CLASS: + return CompletionItemKind.Class; + case ContentAssistEntry.KIND_COLOR: + return CompletionItemKind.Color; + case ContentAssistEntry.KIND_CONSTRUCTOR: + return CompletionItemKind.Constructor; + case ContentAssistEntry.KIND_ENUM: + return CompletionItemKind.Enum; + case ContentAssistEntry.KIND_FIELD: + return CompletionItemKind.Field; + case ContentAssistEntry.KIND_FILE: + return CompletionItemKind.File; + case ContentAssistEntry.KIND_FUNCTION: + return CompletionItemKind.Function; + case ContentAssistEntry.KIND_INTERFACE: + return CompletionItemKind.Interface; + case ContentAssistEntry.KIND_KEYWORD: + return CompletionItemKind.Keyword; + case ContentAssistEntry.KIND_METHOD: + return CompletionItemKind.Method; + case ContentAssistEntry.KIND_MODULE: + return CompletionItemKind.Module; + case ContentAssistEntry.KIND_PROPERTY: + return CompletionItemKind.Property; + case ContentAssistEntry.KIND_REFERENCE: + return CompletionItemKind.Reference; + case ContentAssistEntry.KIND_SNIPPET: + return CompletionItemKind.Snippet; + case ContentAssistEntry.KIND_TEXT: + return CompletionItemKind.Text; + case ContentAssistEntry.KIND_UNIT: + return CompletionItemKind.Unit; + case ContentAssistEntry.KIND_VALUE: + return CompletionItemKind.Value; + case ContentAssistEntry.KIND_VARIABLE: + return CompletionItemKind.Variable; + default: + return CompletionItemKind.Value; + } + } else { + return CompletionItemKind.Value; + } + } + + protected TextEdit toTextEdit(ReplaceRegion region, Document doc) { + Position start = null; + if (region.getOffset() > doc.getContents().length()) { + Position docEnd = doc.getPosition(doc.getContents().length()); + start = new Position(docEnd.getLine(), docEnd.getCharacter() + region.getLength()); + } else { + start = doc.getPosition(region.getOffset()); + } + Position end = null; + if (region.getEndOffset() > doc.getContents().length()) { + end = new Position(start.getLine(), start.getCharacter() + region.getLength()); + } else { + end = doc.getPosition(region.getEndOffset()); + } + return new TextEdit(new Range(start, end), region.getText()); + } +} diff --git a/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/contentassist/ContentAssistService.xtend b/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/contentassist/ContentAssistService.xtend deleted file mode 100644 index df7d42c99e..0000000000 --- a/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/contentassist/ContentAssistService.xtend +++ /dev/null @@ -1,152 +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.server.contentassist - -import com.google.common.base.Strings -import com.google.inject.Inject -import com.google.inject.Provider -import com.google.inject.Singleton -import java.util.ArrayList -import java.util.concurrent.ExecutorService -import org.eclipse.lsp4j.CompletionItem -import org.eclipse.lsp4j.CompletionItemKind -import org.eclipse.lsp4j.CompletionList -import org.eclipse.lsp4j.CompletionParams -import org.eclipse.lsp4j.InsertTextFormat -import org.eclipse.lsp4j.Position -import org.eclipse.lsp4j.Range -import org.eclipse.lsp4j.TextEdit -import org.eclipse.xtext.ide.editor.contentassist.ContentAssistEntry -import org.eclipse.xtext.ide.editor.contentassist.IIdeContentProposalAcceptor -import org.eclipse.xtext.ide.editor.contentassist.IdeContentProposalAcceptor -import org.eclipse.xtext.ide.editor.contentassist.IdeContentProposalProvider -import org.eclipse.xtext.ide.editor.contentassist.antlr.ContentAssistContextFactory -import org.eclipse.xtext.ide.server.Document -import org.eclipse.xtext.resource.XtextResource -import org.eclipse.xtext.service.OperationCanceledManager -import org.eclipse.xtext.util.CancelIndicator -import org.eclipse.xtext.util.ReplaceRegion -import org.eclipse.xtext.util.TextRegion - -/** - * @author kosyakov - Initial contribution and API - * @author Dennis Huebner - additionalTextEdits support - * - * @since 2.11 - */ -@Singleton -class ContentAssistService { - - public static val DEFAULT_PROPOSALS_LIMIT = 1000 - - @Inject Provider contextFactoryProvider - - @Inject ExecutorService executorService - - @Inject IdeContentProposalProvider proposalProvider - - @Inject Provider proposalAcceptorProvider - - @Inject OperationCanceledManager operationCanceledManager - - def CompletionList createCompletionList(Document document, XtextResource resource, - CompletionParams params, CancelIndicator cancelIndicator) { - val result = new CompletionList - // we set isInComplete to true, so we get asked always, which is the best match to the expected behavior in Xtext - result.setIsIncomplete(true); - - val acceptor = proposalAcceptorProvider.get - val caretOffset = document.getOffSet(params.position) - val caretPosition = params.position - val position = new TextRegion(caretOffset, 0) - try { - createProposals(document.contents, position, caretOffset, resource, acceptor) - } catch (Throwable t) { - if (!operationCanceledManager.isOperationCanceledException(t)) { - throw t - } - } - acceptor.getEntries().forEach [ it, idx | - val item = toCompletionItem(caretOffset, caretPosition, document) - item.sortText = Strings.padStart(Integer.toString(idx), 5, "0") - result.items += item - ] - return result - } - - protected def void createProposals(String document, TextRegion selection, int caretOffset, XtextResource resource, IIdeContentProposalAcceptor acceptor) { - if(caretOffset > document.length) return; - - val contextFactory = contextFactoryProvider.get - contextFactory.pool = executorService - val contexts = contextFactory.create(document, selection, caretOffset, resource) - proposalProvider.createProposals(contexts, acceptor) - } - - protected def CompletionItem toCompletionItem(ContentAssistEntry entry, int caretOffset, - Position caretPosition, Document document) { - val completionItem = new CompletionItem - completionItem.label = entry.label ?: entry.proposal - completionItem.detail = entry.description - completionItem.documentation = entry.documentation - val prefixOffset = caretOffset - (entry.prefix ?: '').length - val prefixPosition = document.getPosition(prefixOffset) - completionItem.textEdit = new TextEdit(new Range(prefixPosition, caretPosition), entry.proposal) - completionItem.kind = translateKind(entry) - if (!entry.textReplacements.empty) { - if (completionItem.additionalTextEdits === null) { - completionItem.additionalTextEdits = new ArrayList(entry.textReplacements.size) - } - entry.textReplacements.forEach [ - completionItem.additionalTextEdits += toTextEdit(document) - ] - } - if (entry.kind == ContentAssistEntry.KIND_SNIPPET) { - completionItem.insertTextFormat = InsertTextFormat.Snippet - } - return completionItem - } - - protected def translateKind(ContentAssistEntry entry) { - switch entry.kind { - case ContentAssistEntry.KIND_CLASS: CompletionItemKind.Class - case ContentAssistEntry.KIND_COLOR: CompletionItemKind.Color - case ContentAssistEntry.KIND_CONSTRUCTOR: CompletionItemKind.Constructor - case ContentAssistEntry.KIND_ENUM: CompletionItemKind.Enum - case ContentAssistEntry.KIND_FIELD: CompletionItemKind.Field - case ContentAssistEntry.KIND_FILE: CompletionItemKind.File - case ContentAssistEntry.KIND_FUNCTION: CompletionItemKind.Function - case ContentAssistEntry.KIND_INTERFACE: CompletionItemKind.Interface - case ContentAssistEntry.KIND_KEYWORD: CompletionItemKind.Keyword - case ContentAssistEntry.KIND_METHOD: CompletionItemKind.Method - case ContentAssistEntry.KIND_MODULE: CompletionItemKind.Module - case ContentAssistEntry.KIND_PROPERTY: CompletionItemKind.Property - case ContentAssistEntry.KIND_REFERENCE: CompletionItemKind.Reference - case ContentAssistEntry.KIND_SNIPPET: CompletionItemKind.Snippet - case ContentAssistEntry.KIND_TEXT: CompletionItemKind.Text - case ContentAssistEntry.KIND_UNIT: CompletionItemKind.Unit - case ContentAssistEntry.KIND_VALUE: CompletionItemKind.Value - case ContentAssistEntry.KIND_VARIABLE: CompletionItemKind.Variable - default: CompletionItemKind.Value - } - } - - protected def toTextEdit(ReplaceRegion region, Document doc) { - val start = if (region.offset > doc.contents.length) { - val docEnd = doc.getPosition(doc.contents.length) - new Position(docEnd.line, docEnd.character + region.length) - } else - doc.getPosition(region.offset) - val end = if (region.endOffset > doc.contents.length) - new Position(start.line, start.character + region.length) - else - doc.getPosition(region.endOffset) - new TextEdit(new Range(start, end), region.text) - } -} diff --git a/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/rename/ChangeConverter2.java b/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/rename/ChangeConverter2.java new file mode 100644 index 0000000000..73c1361bbc --- /dev/null +++ b/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/rename/ChangeConverter2.java @@ -0,0 +1,191 @@ +/** + * Copyright (c) 2019, 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.server.rename; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.concurrent.ExecutionException; + +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.xmi.XMLResource; +import org.eclipse.lsp4j.ClientCapabilities; +import org.eclipse.lsp4j.InitializeParams; +import org.eclipse.lsp4j.Position; +import org.eclipse.lsp4j.Range; +import org.eclipse.lsp4j.TextDocumentEdit; +import org.eclipse.lsp4j.TextEdit; +import org.eclipse.lsp4j.VersionedTextDocumentIdentifier; +import org.eclipse.lsp4j.WorkspaceClientCapabilities; +import org.eclipse.lsp4j.WorkspaceEdit; +import org.eclipse.lsp4j.WorkspaceEditCapabilities; +import org.eclipse.lsp4j.jsonrpc.messages.Either; +import org.eclipse.xtext.formatting2.regionaccess.ITextReplacement; +import org.eclipse.xtext.ide.serializer.IEmfResourceChange; +import org.eclipse.xtext.ide.serializer.ITextDocumentChange; +import org.eclipse.xtext.ide.server.Document; +import org.eclipse.xtext.ide.server.ILanguageServerAccess; +import org.eclipse.xtext.ide.server.UriExtensions; +import org.eclipse.xtext.parser.IEncodingProvider; +import org.eclipse.xtext.resource.IResourceServiceProvider; +import org.eclipse.xtext.util.IAcceptor; +import org.eclipse.xtext.xbase.lib.Exceptions; + +import com.google.common.collect.Lists; +import com.google.inject.Inject; + +/** + * @author koehnlein - Initial contribution and API + * @since 2.18 + */ +public class ChangeConverter2 implements IAcceptor { + public static class Factory { + @Inject + protected IResourceServiceProvider.Registry registry; + + @Inject + protected UriExtensions uriExtensions; + + /** + * @since 2.18 + */ + public ChangeConverter2 create(WorkspaceEdit edit, ILanguageServerAccess access) { + return new ChangeConverter2(registry, edit, access, uriExtensions); + } + } + + private IResourceServiceProvider.Registry registry; + + private UriExtensions uriExtensions; + + private WorkspaceEdit edit; + + private ILanguageServerAccess access; + + private boolean useDocumentChanges; + + protected ChangeConverter2(IResourceServiceProvider.Registry registry, WorkspaceEdit edit, + ILanguageServerAccess access, UriExtensions uriExtensions) { + this.registry = registry; + this.uriExtensions = uriExtensions; + this.edit = edit; + this.access = access; + Boolean documentChanges = null; + if (access != null) { + InitializeParams initializeParams = access.getInitializeParams(); + if (initializeParams != null) { + ClientCapabilities clientCapabilities = initializeParams.getCapabilities(); + if (clientCapabilities != null) { + WorkspaceClientCapabilities workspaceClientCapabilities = clientCapabilities.getWorkspace(); + if (workspaceClientCapabilities != null) { + WorkspaceEditCapabilities workspaceEditCapabilities = workspaceClientCapabilities + .getWorkspaceEdit(); + if (workspaceEditCapabilities != null) { + documentChanges = workspaceEditCapabilities.getDocumentChanges(); + } + } + } + } + } + this.useDocumentChanges = documentChanges == Boolean.TRUE; + if (this.useDocumentChanges) { + this.edit.setDocumentChanges(new ArrayList<>()); + } else { + this.edit.setChanges(new LinkedHashMap<>()); + } + } + + @Override + public void accept(IEmfResourceChange change) { + handleReplacements(change); + } + + protected void _handleReplacements(IEmfResourceChange change) { + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + String uri = uriExtensions.toUriString(change.getResource().getURI()); + change.getResource().save(outputStream, null); + String newContent = new String(outputStream.toByteArray(), getCharset(change.getResource())); + access.doRead(uri, (ILanguageServerAccess.Context context) -> { + Document document = context.getDocument(); + Range range = new Range(document.getPosition(0), document.getPosition(document.getContents().length())); + TextEdit textEdit = new TextEdit(range, newContent); + return addTextEdit(uri, document, textEdit); + }).get(); + } catch (InterruptedException | ExecutionException | IOException e) { + throw Exceptions.sneakyThrow(e); + } + } + + protected String getCharset(Resource resource) { + IEncodingProvider xtextEncodingProvider = registry.getResourceServiceProvider(resource.getURI()) + .get(IEncodingProvider.class); + if (xtextEncodingProvider != null) { + return xtextEncodingProvider.getEncoding(resource.getURI()); + } else { + if (resource instanceof XMLResource) { + return ((XMLResource) resource).getEncoding(); + } else { + return Charset.defaultCharset().toString(); + } + } + } + + protected void _handleReplacements(ITextDocumentChange change) { + try { + if (change.getReplacements().size() > 0) { + String uri = uriExtensions.toUriString(change.getNewURI()); + access.doRead(uri, (ILanguageServerAccess.Context context) -> { + Document document = context.getDocument(); + List textEdits = Lists.transform(change.getReplacements(), + (ITextReplacement replacement) -> { + Position start = document.getPosition(replacement.getOffset()); + Position end = document.getPosition(replacement.getOffset() + replacement.getLength()); + Range range = new Range(start, end); + return new TextEdit(range, replacement.getReplacementText()); + }); + return addTextEdit(uri, document, textEdits.toArray(new TextEdit[textEdits.size()])); + }).get(); + } + } catch (InterruptedException | ExecutionException e) { + throw Exceptions.sneakyThrow(e); + } + } + + protected Object addTextEdit(String theUri, Document document, TextEdit... textEdits) { + if (useDocumentChanges) { + TextDocumentEdit textDocumentEdit = new TextDocumentEdit(); + VersionedTextDocumentIdentifier versionedTextDocumentIdentifier = new VersionedTextDocumentIdentifier(); + versionedTextDocumentIdentifier.setUri(theUri); + versionedTextDocumentIdentifier.setVersion(document.getVersion()); + textDocumentEdit.setTextDocument(versionedTextDocumentIdentifier); + textDocumentEdit.setEdits(Arrays.asList(textEdits)); + return edit.getDocumentChanges().add(Either.forLeft(textDocumentEdit)); + } else { + return edit.getChanges().put(theUri, Arrays.asList(textEdits)); + } + } + + protected void handleReplacements(IEmfResourceChange change) { + if (change instanceof ITextDocumentChange) { + _handleReplacements((ITextDocumentChange) change); + return; + } else if (change != null) { + _handleReplacements(change); + return; + } else { + throw new IllegalArgumentException( + "Unhandled parameter types: " + Arrays.asList(change).toString()); + } + } +} diff --git a/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/rename/ChangeConverter2.xtend b/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/rename/ChangeConverter2.xtend deleted file mode 100644 index e9bca81c93..0000000000 --- a/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/rename/ChangeConverter2.xtend +++ /dev/null @@ -1,126 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 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.server.rename - -import com.google.inject.Inject -import java.io.ByteArrayOutputStream -import java.nio.charset.Charset -import org.eclipse.emf.ecore.resource.Resource -import org.eclipse.emf.ecore.xmi.XMLResource -import org.eclipse.lsp4j.Range -import org.eclipse.lsp4j.TextDocumentEdit -import org.eclipse.lsp4j.TextEdit -import org.eclipse.lsp4j.VersionedTextDocumentIdentifier -import org.eclipse.lsp4j.WorkspaceEdit -import org.eclipse.lsp4j.jsonrpc.messages.Either -import org.eclipse.xtext.ide.serializer.IEmfResourceChange -import org.eclipse.xtext.ide.serializer.ITextDocumentChange -import org.eclipse.xtext.ide.server.Document -import org.eclipse.xtext.ide.server.ILanguageServerAccess -import org.eclipse.xtext.ide.server.UriExtensions -import org.eclipse.xtext.parser.IEncodingProvider -import org.eclipse.xtext.resource.IResourceServiceProvider -import org.eclipse.xtext.util.IAcceptor - -/** - * @author koehnlein - Initial contribution and API - * @since 2.18 - */ -class ChangeConverter2 implements IAcceptor { - - static class Factory { - - @Inject protected IResourceServiceProvider.Registry registry - @Inject protected UriExtensions uriExtensions - - /** - * @since 2.18 - */ - def ChangeConverter2 create(WorkspaceEdit edit, ILanguageServerAccess access) { - new ChangeConverter2(registry, edit, access, uriExtensions) - } - } - - val IResourceServiceProvider.Registry registry - val extension UriExtensions uriExtensions - val WorkspaceEdit edit - val ILanguageServerAccess access - val boolean useDocumentChanges - - protected new(IResourceServiceProvider.Registry registry, WorkspaceEdit edit, ILanguageServerAccess access, UriExtensions uriExtensions) { - this.registry = registry - this.uriExtensions = uriExtensions - this.edit = edit - this.access = access - this.useDocumentChanges = access?.initializeParams?.capabilities?.workspace?.workspaceEdit?.documentChanges === Boolean.TRUE - if (useDocumentChanges) - this.edit.documentChanges = newArrayList - else - this.edit.changes = newLinkedHashMap - } - - override accept(IEmfResourceChange change) { - handleReplacements(change) - } - - protected def dispatch void handleReplacements(IEmfResourceChange change) { - val outputStream = new ByteArrayOutputStream - val uri = change.resource.URI.toUriString - change.resource.save(outputStream, null) - val newContent = new String(outputStream.toByteArray, change.resource.charset) - access.doRead(uri) [ context | - val document = context.document - val range = new Range(document.getPosition(0), document.getPosition(document.contents.length)) - val textEdit = new TextEdit(range, newContent) - addTextEdit(uri, document, textEdit) - ].get - } - - protected def String getCharset(Resource resource) { - val xtextEncodingProvider = registry.getResourceServiceProvider(resource.URI).get(IEncodingProvider) - if (xtextEncodingProvider !== null) - return xtextEncodingProvider.getEncoding(resource.URI) - else if (resource instanceof XMLResource) - resource.encoding - else - Charset.defaultCharset.toString - } - - protected def dispatch void handleReplacements(ITextDocumentChange change) { - if (change.replacements.size > 0) { - val uri = change.newURI.toUriString - access.doRead(uri) [ context | - val document = context.document - val textEdits = change.replacements.map [ replacement | - val start = document.getPosition(replacement.offset) - val end = document.getPosition(replacement.offset + replacement.length) - val range = new Range(start, end) - new TextEdit(range, replacement.replacementText) - ] - addTextEdit(uri, document, textEdits) - ].get - } - } - - protected def addTextEdit(String theUri, Document document, TextEdit... textEdits) { - if (useDocumentChanges) { - edit.documentChanges += - Either.forLeft(new TextDocumentEdit => [ - textDocument = new VersionedTextDocumentIdentifier => [ - uri = theUri - version = document.version - ] - edits = textEdits - ]) - } else { - edit.changes.put(theUri, textEdits) - } - } - -} diff --git a/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/rename/RenameService2.java b/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/rename/RenameService2.java new file mode 100644 index 0000000000..aeceef9602 --- /dev/null +++ b/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/rename/RenameService2.java @@ -0,0 +1,373 @@ +/** + * Copyright (c) 2019, 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.server.rename; + +import java.io.FileNotFoundException; +import java.util.concurrent.ExecutionException; + +import org.apache.log4j.Logger; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.lsp4j.InitializeResult; +import org.eclipse.lsp4j.Position; +import org.eclipse.lsp4j.PrepareRenameParams; +import org.eclipse.lsp4j.PrepareRenameResult; +import org.eclipse.lsp4j.Range; +import org.eclipse.lsp4j.RenameOptions; +import org.eclipse.lsp4j.RenameParams; +import org.eclipse.lsp4j.ServerCapabilities; +import org.eclipse.lsp4j.TextDocumentIdentifier; +import org.eclipse.lsp4j.WorkspaceEdit; +import org.eclipse.lsp4j.jsonrpc.messages.Either; +import org.eclipse.lsp4j.util.Ranges; +import org.eclipse.xtext.CrossReference; +import org.eclipse.xtext.RuleCall; +import org.eclipse.xtext.conversion.IValueConverterService; +import org.eclipse.xtext.ide.refactoring.IRenameStrategy2; +import org.eclipse.xtext.ide.refactoring.RefactoringIssueAcceptor; +import org.eclipse.xtext.ide.refactoring.RenameChange; +import org.eclipse.xtext.ide.refactoring.RenameContext; +import org.eclipse.xtext.ide.serializer.IChangeSerializer; +import org.eclipse.xtext.ide.server.Document; +import org.eclipse.xtext.ide.server.ILanguageServerAccess; +import org.eclipse.xtext.linking.impl.LinkingHelper; +import org.eclipse.xtext.nodemodel.ICompositeNode; +import org.eclipse.xtext.nodemodel.ILeafNode; +import org.eclipse.xtext.nodemodel.util.NodeModelUtils; +import org.eclipse.xtext.parser.IParseResult; +import org.eclipse.xtext.parsetree.reconstr.impl.TokenUtil; +import org.eclipse.xtext.resource.EObjectAtOffsetHelper; +import org.eclipse.xtext.resource.IResourceServiceProvider; +import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.util.CancelIndicator; +import org.eclipse.xtext.util.SimpleAttributeResolver; +import org.eclipse.xtext.util.Strings; +import org.eclipse.xtext.xbase.lib.Exceptions; + +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Throwables; +import com.google.common.collect.Lists; +import com.google.inject.Inject; +import com.google.inject.Provider; + +/** + * @author koehnlein - Initial contribution and API + * @since 2.18 + */ +public class RenameService2 implements IRenameService2 { + + private static final Logger LOG = Logger.getLogger(RenameService2.class); + @Inject + private EObjectAtOffsetHelper eObjectAtOffsetHelper; + + @Inject + private Provider issueProvider; + + @Inject + private IResourceServiceProvider.Registry serviceProviderRegistry; + + @Inject + private TokenUtil tokenUtil; + + @Inject + private IValueConverterService valueConverterService; + + @Inject + private LinkingHelper linkingHelper; + + private Function attributeResolver = SimpleAttributeResolver.newResolver(String.class, "name"); + + @Override + public WorkspaceEdit rename(IRenameService2.Options options) { + try { + TextDocumentIdentifier textDocument = options.getRenameParams().getTextDocument(); + String uri = textDocument.getUri(); + ServerRefactoringIssueAcceptor issueAcceptor = issueProvider.get(); + boolean shouldPrepareRename = shouldPrepareRename(options.getLanguageServerAccess()); + return options.getLanguageServerAccess().doRead(uri, (ILanguageServerAccess.Context context) -> { + if (shouldPrepareRename) { + TextDocumentIdentifier identifier = new TextDocumentIdentifier(textDocument.getUri()); + Position position = options.getRenameParams().getPosition(); + PrepareRenameParams positionParams = new PrepareRenameParams(identifier, position); + Resource resource = context.getResource(); + Document document = context.getDocument(); + CancelIndicator cancelIndicator = options.getCancelIndicator(); + Either prepareRenameResult = doPrepareRename(resource, document, + positionParams, cancelIndicator); + if (!mayPerformRename(prepareRenameResult, options.getRenameParams())) { + return null; + } + } + WorkspaceEdit workspaceEdit = new WorkspaceEdit(); + ResourceSet resourceSet = options.getLanguageServerAccess() + .newLiveScopeResourceSet(context.getResource().getURI()); + Resource xtextResource = resourceSet.getResource(context.getResource().getURI(), true); + if (xtextResource instanceof XtextResource) { + Position position = options.getRenameParams().getPosition(); + EObject element = null; + try { + element = getElementAtOffset((XtextResource) xtextResource, context.getDocument(), position); + } catch (IndexOutOfBoundsException e) { + issueAcceptor.add(RefactoringIssueAcceptor.Severity.FATAL, + "Invalid document " + toPositionFragment(position, uri)); + } + if (element == null || element.eIsProxy()) { + issueAcceptor.add(RefactoringIssueAcceptor.Severity.FATAL, + "No element found at " + toPositionFragment(position, uri)); + } else { + IResourceServiceProvider services = serviceProviderRegistry + .getResourceServiceProvider(element.eResource().getURI()); + IChangeSerializer changeSerializer = services.get(IChangeSerializer.class); + RenameChange change = new RenameChange(options.getRenameParams().getNewName(), + EcoreUtil.getURI(element)); + RenameContext renameContext = new RenameContext(Lists.newArrayList(change), resourceSet, + changeSerializer, issueAcceptor); + IRenameStrategy2 renameStrategy = services.get(IRenameStrategy2.class); + renameStrategy.applyRename(renameContext); + ChangeConverter2.Factory converterFactory = services.get( + ChangeConverter2.Factory.class); + ChangeConverter2 changeConverter = converterFactory.create(workspaceEdit, + options.getLanguageServerAccess()); + changeSerializer.applyModifications(changeConverter); + } + } else { + issueAcceptor.add(RefactoringIssueAcceptor.Severity.FATAL, + "Loaded resource is not an XtextResource", context.getResource().getURI()); + } + issueAcceptor.checkSeverity(); + return workspaceEdit; + }).exceptionally((Throwable exception) -> { + try { + Throwable rootCause = Throwables.getRootCause(exception); + if (rootCause instanceof FileNotFoundException) { + if (shouldPrepareRename) { + return null; + } + } + throw exception; + } catch (Throwable e) { + throw Exceptions.sneakyThrow(e); + } + }).get(); + } catch (InterruptedException | ExecutionException e) { + throw Exceptions.sneakyThrow(e); + } + } + + protected EObject getElementAtOffset(XtextResource xtextResource, Document document, Position caretPosition) { + int caretOffset = document.getOffSet(caretPosition); + EObject element = getElementWithIdentifierAt(xtextResource, caretOffset); + if (element != null) { + return element; + } else { + return getElementWithIdentifierAt(xtextResource, caretOffset - 1); + } + } + + protected EObject getElementWithIdentifierAt(XtextResource xtextResource, int offset) { + if (offset >= 0) { + if (xtextResource != null) { + IParseResult parseResult = xtextResource.getParseResult(); + if (parseResult != null) { + ICompositeNode rootNode = parseResult.getRootNode(); + if (rootNode != null) { + ILeafNode leaf = NodeModelUtils.findLeafNodeAtOffset(rootNode, offset); + if (leaf != null && isIdentifier(leaf)) { + return eObjectAtOffsetHelper.resolveElementAt(xtextResource, offset); + } + } + } + } + } + return null; + } + + protected boolean isIdentifier(ILeafNode leafNode) { + return (leafNode.getGrammarElement() instanceof RuleCall + || leafNode.getGrammarElement() instanceof CrossReference) + && !tokenUtil.isWhitespaceOrCommentNode(leafNode); + } + + @Override + public Either prepareRename(IRenameService2.PrepareRenameOptions options) { + try { + String uri = options.getParams().getTextDocument().getUri(); + boolean shouldPrepareRename = shouldPrepareRename(options.getLanguageServerAccess()); + return options.getLanguageServerAccess().doRead(uri, (ILanguageServerAccess.Context context) -> { + if (!shouldPrepareRename) { + return null; + } + Resource resource = context.getResource(); + Document document = context.getDocument(); + PrepareRenameParams params = options.getParams(); + CancelIndicator cancelIndicator = options.getCancelIndicator(); + return doPrepareRename(resource, document, params, cancelIndicator); + }).exceptionally((Throwable exception) -> { + try { + Throwable rootCause = Throwables.getRootCause(exception); + if (rootCause instanceof FileNotFoundException) { + if (shouldPrepareRename) { + return null; + } + } + throw exception; + } catch (Throwable e) { + throw Exceptions.sneakyThrow(e); + } + }).get(); + } catch (InterruptedException | ExecutionException e) { + throw Exceptions.sneakyThrow(e); + } + } + + protected Either doPrepareRename(Resource resource, Document document, + PrepareRenameParams params, CancelIndicator cancelIndicator) { + String uri = params.getTextDocument().getUri(); + if (resource instanceof XtextResource) { + ICompositeNode rootNode = null; + XtextResource xtextResource = (XtextResource) resource; + if (xtextResource != null) { + IParseResult parseResult = xtextResource.getParseResult(); + if (parseResult != null) { + rootNode = parseResult.getRootNode(); + } + } + if (rootNode == null) { + RenameService2.LOG.trace("Could not retrieve root node for resource. URI: " + uri); + return null; + } + Position caretPosition = params.getPosition(); + try { + int caretOffset = document.getOffSet(caretPosition); + EObject element = null; + int candidateOffset = caretOffset; + do { + element = getElementWithIdentifierAt(xtextResource, candidateOffset); + if (element != null && !element.eIsProxy()) { + ILeafNode leaf = NodeModelUtils.findLeafNodeAtOffset(rootNode, candidateOffset); + if (leaf != null && isIdentifier(leaf)) { + String convertedNameValue = getConvertedValue(leaf.getGrammarElement(), leaf); + String elementName = getElementName(element); + if (!Strings.isEmpty(convertedNameValue) && !Strings.isEmpty(elementName) + && Objects.equal(convertedNameValue, elementName)) { + Position start = document.getPosition(leaf.getOffset()); + Position end = document.getPosition(leaf.getEndOffset()); + return Either.forLeft(new Range(start, end)); + } + } + } + candidateOffset = (candidateOffset - 1); + } while (((candidateOffset >= 0) && ((candidateOffset + 1) >= caretOffset))); + } catch (IndexOutOfBoundsException e) { + RenameService2.LOG.trace("Invalid document " + toPositionFragment(caretPosition, uri)); + return null; + } + RenameService2.LOG.trace("No element found at " + toPositionFragment(caretPosition, uri)); + } else { + RenameService2.LOG.trace("Loaded resource is not an XtextResource. URI: " + resource.getURI()); + } + return null; + } + + protected String getConvertedValue(EObject grammarElement, ILeafNode leaf) { + try { + if (grammarElement instanceof RuleCall) { + return valueConverterService + .toValue(leaf.getText(), ((RuleCall) grammarElement).getRule().getName(), leaf).toString(); + } else if (grammarElement instanceof CrossReference) { + return linkingHelper.getCrossRefNodeAsString(leaf, true); + } + } catch (Exception e) { + // The current name text cannot be converted to a value. + // Rename could be used to fix this. + } + return leaf.getText(); + } + + /** + * If this method returns {@code false}, it is sure, that the rename operation will fail. There is no guarantee that + * it will succeed even if it returns {@code true}. + */ + protected boolean mayPerformRename(Either prepareRenameResult, + RenameParams renameParams) { + return prepareRenameResult != null && prepareRenameResult.getLeft() != null + && Ranges.containsPosition(prepareRenameResult.getLeft(), renameParams.getPosition()); + } + + /** + * Tries to read the {@code name} {@link EAttribute} from the the given {@code element}. + * + * It never returns an empty string, but a {@code null} instead. + */ + protected String getElementName(EObject element) { + if (element == null) { + return null; + } + String name = attributeResolver.apply(element); + if (Strings.isEmpty(name)) { + return null; + } else { + return name; + } + } + + private String toPositionFragment(Position it, String uri) { + return "position line: " + it.getLine() + " column: " + it.getCharacter() + " in resource: " + uri; + } + + private boolean shouldPrepareRename(ILanguageServerAccess access) { + Either provider = null; + if (access != null) { + InitializeResult initializeResult = access.getInitializeResult(); + if (initializeResult != null) { + ServerCapabilities capabilities = initializeResult.getCapabilities(); + if (capabilities != null) { + provider = capabilities.getRenameProvider(); + } + } + } + if (provider != null && provider.isRight()) { + return Boolean.TRUE.equals(provider.getRight().getPrepareProvider()); + } else { + return false; + } + } + + protected EObjectAtOffsetHelper getEObjectAtOffsetHelper() { + return eObjectAtOffsetHelper; + } + + protected Provider getIssueProvider() { + return issueProvider; + } + + protected IResourceServiceProvider.Registry getServiceProviderRegistry() { + return serviceProviderRegistry; + } + + protected TokenUtil getTokenUtil() { + return tokenUtil; + } + + protected IValueConverterService getValueConverterService() { + return valueConverterService; + } + + protected LinkingHelper getLinkingHelper() { + return linkingHelper; + } + + protected Function getAttributeResolver() { + return attributeResolver; + } +} diff --git a/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/rename/RenameService2.xtend b/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/rename/RenameService2.xtend deleted file mode 100644 index c5ad2080d4..0000000000 --- a/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/rename/RenameService2.xtend +++ /dev/null @@ -1,275 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 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.server.rename - -import com.google.common.base.Function -import com.google.common.base.Throwables -import com.google.inject.Inject -import com.google.inject.Provider -import java.io.FileNotFoundException -import org.eclipse.emf.ecore.EAttribute -import org.eclipse.emf.ecore.EObject -import org.eclipse.emf.ecore.resource.Resource -import org.eclipse.emf.ecore.util.EcoreUtil -import org.eclipse.lsp4j.Position -import org.eclipse.lsp4j.PrepareRenameParams -import org.eclipse.lsp4j.PrepareRenameResult -import org.eclipse.lsp4j.Range -import org.eclipse.lsp4j.RenameParams -import org.eclipse.lsp4j.TextDocumentIdentifier -import org.eclipse.lsp4j.WorkspaceEdit -import org.eclipse.lsp4j.jsonrpc.messages.Either -import org.eclipse.xtend.lib.annotations.Accessors -import org.eclipse.xtext.CrossReference -import org.eclipse.xtext.RuleCall -import org.eclipse.xtext.conversion.IValueConverterService -import org.eclipse.xtext.ide.refactoring.IRenameStrategy2 -import org.eclipse.xtext.ide.refactoring.RenameChange -import org.eclipse.xtext.ide.refactoring.RenameContext -import org.eclipse.xtext.ide.serializer.IChangeSerializer -import org.eclipse.xtext.ide.server.Document -import org.eclipse.xtext.ide.server.ILanguageServerAccess -import org.eclipse.xtext.linking.impl.LinkingHelper -import org.eclipse.xtext.nodemodel.ILeafNode -import org.eclipse.xtext.nodemodel.util.NodeModelUtils -import org.eclipse.xtext.parsetree.reconstr.impl.TokenUtil -import org.eclipse.xtext.resource.EObjectAtOffsetHelper -import org.eclipse.xtext.resource.IResourceServiceProvider -import org.eclipse.xtext.resource.XtextResource -import org.eclipse.xtext.util.CancelIndicator -import org.eclipse.xtext.util.SimpleAttributeResolver -import org.eclipse.xtext.util.Strings -import org.eclipse.xtext.util.internal.Log - -import static org.eclipse.xtext.ide.refactoring.RefactoringIssueAcceptor.Severity.* - -import static extension org.eclipse.lsp4j.util.Ranges.* - -/** - * @author koehnlein - Initial contribution and API - * @since 2.18 - */ -@Log -@Accessors(PROTECTED_GETTER) -class RenameService2 implements IRenameService2 { - - @Inject extension EObjectAtOffsetHelper eObjectAtOffsetHelper - - @Inject Provider issueProvider - - @Inject IResourceServiceProvider.Registry serviceProviderRegistry - - @Inject TokenUtil tokenUtil - - @Inject IValueConverterService valueConverterService - - @Inject LinkingHelper linkingHelper - - Function attributeResolver = SimpleAttributeResolver.newResolver(String, 'name') - - override rename(Options options) { - val textDocument = options.renameParams.textDocument - val uri = textDocument.uri - val issueAcceptor = issueProvider.get - val shouldPrepareRename = options.languageServerAccess.shouldPrepareRename - return options.languageServerAccess.doRead(uri) [ context | - - if (shouldPrepareRename) { - val identifier = new TextDocumentIdentifier(textDocument.uri) - val position = options.renameParams.position - val positionParams = new PrepareRenameParams(identifier, position) - val resource = context.resource - val document = context.document - val cancelIndicator = options.cancelIndicator - - val prepareRenameResult = doPrepareRename(resource, document, positionParams, cancelIndicator) - if (!mayPerformRename(prepareRenameResult, options.renameParams)) { - return null - } - } - - val workspaceEdit = new WorkspaceEdit - val resourceSet = options.languageServerAccess.newLiveScopeResourceSet(context.resource.URI) - val xtextResource = resourceSet.getResource(context.resource.URI, true) - if (xtextResource instanceof XtextResource) { - val position = options.renameParams.position - var EObject element - try { - element = xtextResource.getElementAtOffset(context.document, position) - } catch (IndexOutOfBoundsException exc) { - issueAcceptor.add(FATAL, '''Invalid document «position.toPositionFragment(uri)»''') - } - if (element === null || element.eIsProxy) { - issueAcceptor.add(FATAL, '''No element found at «position.toPositionFragment(uri)»''') - } else { - val services = serviceProviderRegistry.getResourceServiceProvider(element.eResource.URI) - val changeSerializer = services.get(IChangeSerializer) - val change = new RenameChange(options.renameParams.newName, EcoreUtil.getURI(element)) - val renameContext = new RenameContext(#[change], resourceSet, changeSerializer, issueAcceptor) - val renameStrategy = services.get(IRenameStrategy2) - renameStrategy.applyRename(renameContext) - val converterFactory = services.get(ChangeConverter2.Factory) - val changeConverter = converterFactory.create(workspaceEdit, options.languageServerAccess) - changeSerializer.applyModifications(changeConverter) - } - } else { - issueAcceptor.add(FATAL, 'Loaded resource is not an XtextResource', context.resource.URI) - } - issueAcceptor.checkSeverity - return workspaceEdit - ].exceptionally [ exception | - val rootCause = Throwables.getRootCause(exception) - if (rootCause instanceof FileNotFoundException) { - if (shouldPrepareRename) { - return null - } - } - throw exception - ].get - } - - protected def EObject getElementAtOffset(XtextResource xtextResource, Document document, Position caretPosition) { - val caretOffset = document.getOffSet(caretPosition) - return xtextResource.getElementWithIdentifierAt(caretOffset) - ?: xtextResource.getElementWithIdentifierAt(caretOffset - 1) - } - - protected def getElementWithIdentifierAt(XtextResource xtextResource, int offset) { - if (offset >= 0) { - val rootNode = xtextResource?.parseResult?.rootNode - if (rootNode !== null) { - val leaf = NodeModelUtils.findLeafNodeAtOffset(rootNode, offset) - if (leaf !== null && leaf.isIdentifier) { - return xtextResource.resolveElementAt(offset) - } - } - } - return null - } - - protected def isIdentifier(ILeafNode leafNode) { - return (leafNode.grammarElement instanceof RuleCall || leafNode.grammarElement instanceof CrossReference) - && !tokenUtil.isWhitespaceOrCommentNode(leafNode) - } - - override prepareRename(PrepareRenameOptions options) { - val uri = options.params.textDocument.uri - val shouldPrepareRename = options.languageServerAccess.shouldPrepareRename - return options.languageServerAccess.doRead(uri) [ context | - // We check `shouldPrepareRename` here instead of before the `doRead` - // because we still have to propagate the error if the resource is missing. - if (!shouldPrepareRename) { - return null - } - val resource = context.resource - val document = context.document - val params = options.params - val cancelIndicator = options.cancelIndicator - return doPrepareRename(resource, document, params, cancelIndicator) - ].exceptionally [ exception | - val rootCause = Throwables.getRootCause(exception) - if (rootCause instanceof FileNotFoundException) { - if (shouldPrepareRename) { - return null - } - } - throw exception - ].get - } - - protected def Either doPrepareRename(Resource resource, Document document, - PrepareRenameParams params, CancelIndicator cancelIndicator) { - - val uri = params.textDocument.uri - if (resource instanceof XtextResource) { - val rootNode = resource?.parseResult?.rootNode - if (rootNode === null) { - LOG.trace('''Could not retrieve root node for resource. URI: «uri».''') - return null - } - val caretPosition = params.position - try { - val caretOffset = document.getOffSet(caretPosition) - var EObject element - var candidateOffset = caretOffset - do { - element = resource.getElementWithIdentifierAt(candidateOffset) - if (element !== null && !element.eIsProxy) { - val leaf = NodeModelUtils.findLeafNodeAtOffset(rootNode, candidateOffset) - if (leaf !== null && leaf.isIdentifier) { - val convertedNameValue = getConvertedValue(leaf.grammarElement, leaf) - val elementName = element.elementName - if (!convertedNameValue.nullOrEmpty && !elementName.nullOrEmpty && convertedNameValue == elementName) { - val start = document.getPosition(leaf.offset) - val end = document.getPosition(leaf.endOffset) - return Either.forLeft(new Range(start, end)) - } - } - } - candidateOffset = candidateOffset - 1 - } while (candidateOffset >= 0 && candidateOffset + 1 >= caretOffset) - } catch (IndexOutOfBoundsException e) { - LOG.trace('''Invalid document «caretPosition.toPositionFragment(uri)»''') - return null - } - LOG.trace('''No element found at «caretPosition.toPositionFragment(uri)»''') - } else { - LOG.trace('''Loaded resource is not an XtextResource. URI: «resource.URI»''') - } - return null - } - - protected def String getConvertedValue(EObject grammarElement, ILeafNode leaf) { - try { - switch (grammarElement) { - RuleCall: return valueConverterService.toValue(leaf.text, grammarElement.rule.name, leaf).toString() - CrossReference: return linkingHelper.getCrossRefNodeAsString(leaf, true) - } - } catch (Exception exc) { - // The current name text cannot be converted to a value. - // Rename could be used to fix this. - } - return leaf.text - } - - /** - * If this method returns {@code false}, it is sure, that the rename operation will fail. - * There is no guarantee that it will succeed even if it returns {@code true}. - */ - protected def boolean mayPerformRename(Either prepareRenameResult, - RenameParams renameParams) { - - return prepareRenameResult !== null && prepareRenameResult.getLeft !== null && - prepareRenameResult.getLeft.containsPosition(renameParams.position) - } - - /** - * Tries to read the {@code name} {@link EAttribute} from the - * the given {@code element}. - * - * It never returns an empty string, but a {@code null} instead. - */ - protected def getElementName(EObject element) { - if (element === null) { - return null - } - val name = attributeResolver.apply(element) - return if(Strings.isEmpty(name)) null else name - } - - private def toPositionFragment(Position it, String uri) { - return '''position line: «line» column: «character» in resource: «uri»''' - } - - private def shouldPrepareRename(ILanguageServerAccess access) { - val provider = access?.initializeResult?.capabilities?.renameProvider - return if(provider !== null && provider.isRight) Boolean.TRUE == provider.getRight.prepareProvider else false - } - -} diff --git a/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/symbol/DocumentSymbolService.java b/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/symbol/DocumentSymbolService.java new file mode 100644 index 0000000000..7af74e105e --- /dev/null +++ b/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/symbol/DocumentSymbolService.java @@ -0,0 +1,340 @@ +/** + * 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.server.symbol; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.lsp4j.DefinitionParams; +import org.eclipse.lsp4j.DocumentSymbol; +import org.eclipse.lsp4j.DocumentSymbolParams; +import org.eclipse.lsp4j.Location; +import org.eclipse.lsp4j.ReferenceParams; +import org.eclipse.lsp4j.SymbolInformation; +import org.eclipse.lsp4j.SymbolKind; +import org.eclipse.lsp4j.jsonrpc.messages.Either; +import org.eclipse.xtext.findReferences.IReferenceFinder; +import org.eclipse.xtext.findReferences.ReferenceAcceptor; +import org.eclipse.xtext.findReferences.TargetURICollector; +import org.eclipse.xtext.findReferences.TargetURIs; +import org.eclipse.xtext.ide.server.Document; +import org.eclipse.xtext.ide.server.DocumentExtensions; +import org.eclipse.xtext.ide.server.UriExtensions; +import org.eclipse.xtext.ide.util.CancelIndicatorProgressMonitor; +import org.eclipse.xtext.naming.IQualifiedNameProvider; +import org.eclipse.xtext.naming.QualifiedName; +import org.eclipse.xtext.resource.EObjectAtOffsetHelper; +import org.eclipse.xtext.resource.IEObjectDescription; +import org.eclipse.xtext.resource.IReferenceDescription; +import org.eclipse.xtext.resource.IResourceDescription; +import org.eclipse.xtext.resource.IResourceDescriptions; +import org.eclipse.xtext.resource.IResourceServiceProvider; +import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.service.OperationCanceledManager; +import org.eclipse.xtext.util.CancelIndicator; +import org.eclipse.xtext.xbase.lib.Functions.Function1; +import org.eclipse.xtext.xbase.lib.IterableExtensions; +import org.eclipse.xtext.xbase.lib.Procedures.Procedure1; + +import com.google.common.collect.Lists; +import com.google.common.graph.Traverser; +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; + +/** + * @author kosyakov - Initial contribution and API + * @since 2.11 + */ +@Singleton +public class DocumentSymbolService implements IDocumentSymbolService { + @Inject + private UriExtensions uriExtensions; + + @Inject + private DocumentExtensions documentExtensions; + + @Inject + private EObjectAtOffsetHelper eObjectAtOffsetHelper; + + @Inject + private IQualifiedNameProvider qualifiedNameProvider; + + @Inject + private IReferenceFinder referenceFinder; + + @Inject + private TargetURICollector targetURICollector; + + @Inject + private Provider targetURIProvider; + + @Inject + private OperationCanceledManager operationCanceledManager; + + @Inject + private IResourceServiceProvider.Registry resourceServiceProviderRegistry; + + @Inject + private HierarchicalDocumentSymbolService hierarchicalDocumentSymbolService; + + /** + * @since 2.21 + */ + public List getDefinitions(Document document, XtextResource resource, DefinitionParams params, + IReferenceFinder.IResourceAccess resourceAccess, CancelIndicator cancelIndicator) { + int offset = document.getOffSet(params.getPosition()); + return getDefinitions(resource, offset, resourceAccess, cancelIndicator); + } + + public List getDefinitions(XtextResource resource, int offset, + IReferenceFinder.IResourceAccess resourceAccess, CancelIndicator cancelIndicator) { + EObject element = eObjectAtOffsetHelper.resolveElementAt(resource, offset); + if (element == null) { + return Collections.emptyList(); + } + List locations = new ArrayList<>(); + TargetURIs targetURIs = collectTargetURIs(element); + for (URI targetURI : targetURIs) { + operationCanceledManager.checkCanceled(cancelIndicator); + doRead(resourceAccess, targetURI, (EObject obj) -> { + Location location = documentExtensions.newLocation(obj); + if (location != null) { + locations.add(location); + } + }); + } + return locations; + } + + public List getReferences(Document document, XtextResource resource, ReferenceParams params, + IReferenceFinder.IResourceAccess resourceAccess, IResourceDescriptions indexData, + CancelIndicator cancelIndicator) { + int offset = document.getOffSet(params.getPosition()); + List definitions = Collections.emptyList(); + if (params.getContext().isIncludeDeclaration()) { + definitions = getDefinitions(resource, offset, resourceAccess, cancelIndicator); + } + List references = getReferences(resource, offset, resourceAccess, indexData, + cancelIndicator); + List result = new ArrayList<>(); + result.addAll(definitions); + result.addAll(references); + return result; + } + + public List getReferences(XtextResource resource, int offset, + IReferenceFinder.IResourceAccess resourceAccess, IResourceDescriptions indexData, + CancelIndicator cancelIndicator) { + EObject element = eObjectAtOffsetHelper.resolveElementAt(resource, offset); + if (element == null) { + return Collections.emptyList(); + } + List locations = new ArrayList<>(); + TargetURIs targetURIs = collectTargetURIs(element); + referenceFinder.findAllReferences(targetURIs, resourceAccess, indexData, + new ReferenceAcceptor(resourceServiceProviderRegistry, (IReferenceDescription reference) -> { + doRead(resourceAccess, reference.getSourceEObjectUri(), (EObject obj) -> { + Location location = documentExtensions.newLocation(obj, reference.getEReference(), + reference.getIndexInList()); + if (location != null) { + locations.add(location); + } + }); + }), new CancelIndicatorProgressMonitor(cancelIndicator)); + return locations; + } + + protected TargetURIs collectTargetURIs(EObject targetObject) { + TargetURIs targetURIs = targetURIProvider.get(); + targetURICollector.add(targetObject, targetURIs); + return targetURIs; + } + + @Override + public List> getSymbols(Document document, XtextResource resource, + DocumentSymbolParams params, CancelIndicator cancelIndicator) { + return getSymbols(resource, cancelIndicator); + } + + public List> getSymbols(XtextResource resource, + CancelIndicator cancelIndicator) { + String uri = uriExtensions.toUriString(resource.getURI()); + ArrayList infos = new ArrayList<>(); + List rootSymbols = Lists + .transform(hierarchicalDocumentSymbolService.getSymbols(resource, cancelIndicator), Either::getRight); + for (DocumentSymbol rootSymbol : rootSymbols) { + Iterable symbols = Traverser.forTree(DocumentSymbol::getChildren) + .depthFirstPreOrder(rootSymbol); + Function1 containerNameProvider = (DocumentSymbol symbol) -> { + DocumentSymbol firstSymbol = IterableExtensions.findFirst(symbols, (DocumentSymbol it) -> { + return it != symbol && !IterableExtensions.isNullOrEmpty(it.getChildren()) + && it.getChildren().contains(symbol); + }); + if (firstSymbol != null) { + return firstSymbol.getName(); + } + return null; + }; + for (DocumentSymbol s : symbols) { + infos.add(createSymbol(uri, s, containerNameProvider)); + } + } + return Lists.transform(infos, Either::forLeft); + } + + protected EObject getContainer(EObject obj) { + return obj.eContainer(); + } + + /** + * @since 2.16 + */ + protected SymbolInformation createSymbol(String uri, DocumentSymbol symbol, + Function1 containerNameProvider) { + SymbolInformation symbolInformation = new SymbolInformation(); + symbolInformation.setName(symbol.getName()); + symbolInformation.setKind(symbol.getKind()); + symbolInformation.setDeprecated(symbol.getDeprecated()); + Location location = new Location(); + location.setUri(uri); + location.setRange(symbol.getSelectionRange()); + symbolInformation.setLocation(location); + symbolInformation.setContainerName(containerNameProvider.apply(symbol)); + return symbolInformation; + } + + protected SymbolInformation createSymbol(EObject object) { + String name = getSymbolName(object); + if (name == null) { + return null; + } + SymbolKind kind = getSymbolKind(object); + if (kind == null) { + return null; + } + Location location = getSymbolLocation(object); + if (location == null) { + return null; + } + SymbolInformation symbol = new SymbolInformation(); + symbol.setName(name); + symbol.setKind(kind); + symbol.setLocation(location); + return symbol; + } + + protected String getSymbolName(EObject object) { + return getSymbolName(qualifiedNameProvider.getFullyQualifiedName(object)); + } + + protected SymbolKind getSymbolKind(EObject object) { + return getSymbolKind(object.eClass()); + } + + protected Location getSymbolLocation(EObject object) { + return documentExtensions.newLocation(object); + } + + public List getSymbols(IResourceDescription resourceDescription, String query, + IReferenceFinder.IResourceAccess resourceAccess, CancelIndicator cancelIndicator) { + List symbols = new LinkedList<>(); + for (IEObjectDescription description : resourceDescription.getExportedObjects()) { + operationCanceledManager.checkCanceled(cancelIndicator); + if (filter(description, query)) { + createSymbol(description, resourceAccess, (SymbolInformation symbol) -> { + symbols.add(symbol); + }); + } + } + return symbols; + } + + protected boolean filter(IEObjectDescription description, String query) { + return description.getQualifiedName().toLowerCase().toString().contains(query.toLowerCase()); + } + + protected void createSymbol(IEObjectDescription description, IReferenceFinder.IResourceAccess resourceAccess, + Procedure1 acceptor) { + String name = getSymbolName(description); + if (name == null) { + return; + } + SymbolKind kind = getSymbolKind(description); + if (kind == null) { + return; + } + getSymbolLocation(description, resourceAccess, (Location location) -> { + SymbolInformation symbol = new SymbolInformation(name, kind, location); + acceptor.apply(symbol); + }); + } + + protected SymbolInformation createSymbol(IEObjectDescription description) { + String symbolName = getSymbolName(description); + if (symbolName == null) { + return null; + } + SymbolKind symbolKind = getSymbolKind(description); + if (symbolKind == null) { + return null; + } + SymbolInformation symbol = new SymbolInformation(); + symbol.setName(symbolName); + symbol.setKind(symbolKind); + return symbol; + } + + protected String getSymbolName(IEObjectDescription description) { + return getSymbolName(description.getQualifiedName()); + } + + protected SymbolKind getSymbolKind(IEObjectDescription description) { + return getSymbolKind(description.getEClass()); + } + + protected void getSymbolLocation(IEObjectDescription description, IReferenceFinder.IResourceAccess resourceAccess, + Procedure1 acceptor) { + doRead(resourceAccess, description.getEObjectURI(), (EObject obj) -> { + Location location = getSymbolLocation(obj); + if (location != null) { + acceptor.apply(location); + } + }); + } + + protected String getSymbolName(QualifiedName qualifiedName) { + if (qualifiedName != null) { + return qualifiedName.toString(); + } + return null; + } + + protected SymbolKind getSymbolKind(EClass type) { + // TODO implement meaningful + return SymbolKind.Property; + } + + protected void doRead(IReferenceFinder.IResourceAccess resourceAccess, URI objectURI, + Procedure1 acceptor) { + resourceAccess.readOnly(objectURI, (ResourceSet resourceSet) -> { + EObject object = resourceSet.getEObject(objectURI, true); + if (object != null) { + acceptor.apply(object); + } + return null; + }); + } +} diff --git a/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/symbol/DocumentSymbolService.xtend b/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/symbol/DocumentSymbolService.xtend deleted file mode 100644 index 70959c6f0f..0000000000 --- a/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/symbol/DocumentSymbolService.xtend +++ /dev/null @@ -1,343 +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.server.symbol - -import com.google.common.graph.Traverser -import com.google.inject.Inject -import com.google.inject.Provider -import com.google.inject.Singleton -import java.util.List -import org.eclipse.emf.common.util.URI -import org.eclipse.emf.ecore.EClass -import org.eclipse.emf.ecore.EObject -import org.eclipse.lsp4j.DefinitionParams -import org.eclipse.lsp4j.DocumentSymbol -import org.eclipse.lsp4j.DocumentSymbolParams -import org.eclipse.lsp4j.Location -import org.eclipse.lsp4j.ReferenceParams -import org.eclipse.lsp4j.SymbolInformation -import org.eclipse.lsp4j.SymbolKind -import org.eclipse.lsp4j.jsonrpc.messages.Either -import org.eclipse.xtext.findReferences.IReferenceFinder -import org.eclipse.xtext.findReferences.IReferenceFinder.IResourceAccess -import org.eclipse.xtext.findReferences.ReferenceAcceptor -import org.eclipse.xtext.findReferences.TargetURICollector -import org.eclipse.xtext.findReferences.TargetURIs -import org.eclipse.xtext.ide.server.Document -import org.eclipse.xtext.ide.server.DocumentExtensions -import org.eclipse.xtext.ide.server.UriExtensions -import org.eclipse.xtext.ide.util.CancelIndicatorProgressMonitor -import org.eclipse.xtext.naming.IQualifiedNameProvider -import org.eclipse.xtext.naming.QualifiedName -import org.eclipse.xtext.resource.EObjectAtOffsetHelper -import org.eclipse.xtext.resource.IEObjectDescription -import org.eclipse.xtext.resource.IResourceDescription -import org.eclipse.xtext.resource.IResourceDescriptions -import org.eclipse.xtext.resource.IResourceServiceProvider -import org.eclipse.xtext.resource.XtextResource -import org.eclipse.xtext.service.OperationCanceledManager -import org.eclipse.xtext.util.CancelIndicator - -/** - * @author kosyakov - Initial contribution and API - * @since 2.11 - */ -@Singleton -class DocumentSymbolService implements IDocumentSymbolService { - - @Inject - extension UriExtensions - - @Inject - extension DocumentExtensions - - @Inject - extension EObjectAtOffsetHelper - - @Inject - extension IQualifiedNameProvider - - @Inject - IReferenceFinder referenceFinder - - @Inject - TargetURICollector targetURICollector - - @Inject - Provider targetURIProvider - - @Inject - OperationCanceledManager operationCanceledManager - - @Inject - IResourceServiceProvider.Registry resourceServiceProviderRegistry - - @Inject - HierarchicalDocumentSymbolService hierarchicalDocumentSymbolService - - /** - * @since 2.21 - */ - def List getDefinitions( - Document document, - XtextResource resource, - DefinitionParams params, - IResourceAccess resourceAccess, - CancelIndicator cancelIndicator - ) { - val offset = document.getOffSet(params.position) - return getDefinitions(resource, offset, resourceAccess, cancelIndicator) - } - - def List getDefinitions( - XtextResource resource, - int offset, - IResourceAccess resourceAccess, - CancelIndicator cancelIndicator - ) { - val element = resource.resolveElementAt(offset) - if (element === null) - return emptyList - - val locations = newArrayList - val targetURIs = element.collectTargetURIs - for (targetURI : targetURIs) { - operationCanceledManager.checkCanceled(cancelIndicator) - - resourceAccess.doRead(targetURI) [ obj | - val location = obj.newLocation - if (location !== null) - locations += location - ] - } - return locations - } - - def List getReferences( - Document document, - XtextResource resource, - ReferenceParams params, - IResourceAccess resourceAccess, - IResourceDescriptions indexData, - CancelIndicator cancelIndicator - ) { - val offset = document.getOffSet(params.position) - - val definitions = if (params.context.includeDeclaration) - getDefinitions(resource, offset, resourceAccess, cancelIndicator) - else - emptyList - - val references = getReferences(resource, offset, resourceAccess, indexData, cancelIndicator) - val result = definitions + references - return result.toList - } - - def List getReferences( - XtextResource resource, - int offset, - IResourceAccess resourceAccess, - IResourceDescriptions indexData, - CancelIndicator cancelIndicator - ) { - val element = resource.resolveElementAt(offset) - if (element === null) - return emptyList - - val locations = newArrayList - val targetURIs = element.collectTargetURIs - referenceFinder.findAllReferences( - targetURIs, - resourceAccess, - indexData, - new ReferenceAcceptor(resourceServiceProviderRegistry) [ reference | - resourceAccess.doRead(reference.sourceEObjectUri) [ obj | - val location = obj.newLocation(reference.EReference, reference.indexInList) - if (location !== null) - locations += location - ] - ], - new CancelIndicatorProgressMonitor(cancelIndicator) - ) - return locations - } - - protected def TargetURIs collectTargetURIs(EObject targetObject) { - val targetURIs = targetURIProvider.get - targetURICollector.add(targetObject, targetURIs) - return targetURIs - } - - override List> getSymbols( - Document document, - XtextResource resource, - DocumentSymbolParams params, - CancelIndicator cancelIndicator - ) { - return getSymbols(resource, cancelIndicator) - } - - def List> getSymbols(XtextResource resource, CancelIndicator cancelIndicator) { - val uri = resource.URI.toUriString - val infos = newArrayList - val rootSymbols = hierarchicalDocumentSymbolService.getSymbols(resource, cancelIndicator).map[getRight] - rootSymbols.forEach[ rootSymbol | - val symbols = Traverser.forTree([children]).depthFirstPreOrder(rootSymbol) - val (DocumentSymbol)=>String containerNameProvider = [ symbol | - return symbols.findFirst [ - it !== symbol && !children.nullOrEmpty && children.contains(symbol) - ]?.name - ] - infos.addAll(symbols.map[createSymbol(uri, it, containerNameProvider)]) - ] - return infos.map[Either.forLeft(it)] - } - - protected def EObject getContainer(EObject obj) { - return obj.eContainer - } - - /** - * @since 2.16 - */ - protected def SymbolInformation createSymbol(String uri, DocumentSymbol symbol, (DocumentSymbol)=>String containerNameProvider) { - return new SymbolInformation => [ - name = symbol.name - kind = symbol.kind - deprecated = symbol.deprecated - location = new Location => [ - it.uri = uri - range = symbol.selectionRange - ] - containerName = containerNameProvider.apply(symbol) - ] - } - - protected def SymbolInformation createSymbol(EObject object) { - val name = object.symbolName - if(name === null) return null - - val kind = object.symbolKind - if(kind === null) return null - - val location = object.symbolLocation - if(location === null) return null - - val symbol = new SymbolInformation - symbol.name = name - symbol.kind = kind - symbol.location = location - return symbol - } - - protected def String getSymbolName(EObject object) { - return object.fullyQualifiedName.symbolName - } - - protected def SymbolKind getSymbolKind(EObject object) { - return object.eClass.symbolKind - } - - protected def Location getSymbolLocation(EObject object) { - return object.newLocation - } - - def List getSymbols( - IResourceDescription resourceDescription, - String query, - IResourceAccess resourceAccess, - CancelIndicator cancelIndicator - ) { - val symbols = newLinkedList - for (description : resourceDescription.exportedObjects) { - operationCanceledManager.checkCanceled(cancelIndicator) - if (description.filter(query)) { - description.createSymbol(resourceAccess) [ symbol | - symbols += symbol - ] - } - } - return symbols - } - - protected def boolean filter(IEObjectDescription description, String query) { - return description.qualifiedName.toLowerCase.toString.contains(query.toLowerCase) - } - - protected def void createSymbol( - IEObjectDescription description, - IResourceAccess resourceAccess, - (SymbolInformation)=>void acceptor - ) { - val name = description.symbolName - if(name === null) return; - - val kind = description.symbolKind - if(kind === null) return; - - description.getSymbolLocation(resourceAccess) [ location | - val symbol = new SymbolInformation(name, kind, location) - acceptor.apply(symbol) - ] - } - - protected def SymbolInformation createSymbol(IEObjectDescription description) { - val symbolName = description.symbolName - if(symbolName === null) return null; - - val symbolKind = description.symbolKind - if(symbolKind === null) return null; - - val symbol = new SymbolInformation - symbol.name = symbolName - symbol.kind = symbolKind - return symbol; - } - - protected def String getSymbolName(IEObjectDescription description) { - return description.qualifiedName.symbolName - } - - protected def SymbolKind getSymbolKind(IEObjectDescription description) { - return description.EClass.symbolKind - } - - protected def void getSymbolLocation( - IEObjectDescription description, - IResourceAccess resourceAccess, - (Location)=>void acceptor - ) { - resourceAccess.doRead(description.EObjectURI) [ obj | - val location = obj.symbolLocation - if (location !== null) { - acceptor.apply(location) - } - ] - } - - protected def String getSymbolName(QualifiedName qualifiedName) { - return qualifiedName?.toString - } - - protected def SymbolKind getSymbolKind(EClass type) { - // TODO implement meaningful - return SymbolKind.Property - } - - protected def void doRead(IResourceAccess resourceAccess, URI objectURI, (EObject)=>void acceptor) { - resourceAccess.readOnly(objectURI) [ resourceSet | - val object = resourceSet.getEObject(objectURI, true) - if (object !== null) { - acceptor.apply(object) - } - return null - ] - } - -} diff --git a/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/symbol/HierarchicalDocumentSymbolService.java b/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/symbol/HierarchicalDocumentSymbolService.java new file mode 100644 index 0000000000..09c18e8c2c --- /dev/null +++ b/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/symbol/HierarchicalDocumentSymbolService.java @@ -0,0 +1,130 @@ +/** + * 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.server.symbol; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.lsp4j.DocumentSymbol; +import org.eclipse.lsp4j.DocumentSymbolParams; +import org.eclipse.lsp4j.SymbolInformation; +import org.eclipse.lsp4j.jsonrpc.messages.Either; +import org.eclipse.lsp4j.jsonrpc.validation.NonNull; +import org.eclipse.xtext.ide.server.Document; +import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.service.OperationCanceledManager; +import org.eclipse.xtext.util.CancelIndicator; +import org.eclipse.xtext.xbase.lib.Exceptions; + +import com.google.common.annotations.Beta; +import com.google.common.base.Optional; +import com.google.inject.Inject; +import com.google.inject.Singleton; + +/** + * Document symbol service that is comply with the LSP + * 3.10.0 version. + * Unlike the {@link DocumentSymbolService}, this service can provide hierarchical document symbols. + */ +@Beta +@Singleton +public class HierarchicalDocumentSymbolService implements IDocumentSymbolService { + @Inject + private DocumentSymbolMapper symbolMapper; + + @Inject + private OperationCanceledManager operationCanceledManager; + + /** + * {@code false} if the argument is {@code null} or any of the {@link NonNull} properties are {@code null}. + * Otherwise, {@code true}. + */ + public static boolean isValid(DocumentSymbol symbol) { + if (symbol != null) { + for (Field field : DocumentSymbol.class.getDeclaredFields()) { + for (Annotation annotation : field.getAnnotations()) { + if (NonNull.class == annotation.annotationType()) { + field.setAccessible(true); + try { + Object o = field.get(symbol); + if (o == null) { + return false; + } + } catch (Throwable e) { + throw Exceptions.sneakyThrow(e); + } + } + } + } + return true; + } + return false; + + } + + @Override + public List> getSymbols(Document document, XtextResource resource, + DocumentSymbolParams params, CancelIndicator cancelIndicator) { + return getSymbols(resource, cancelIndicator); + } + + public List> getSymbols(XtextResource resource, + CancelIndicator cancelIndicator) { + HashMap allSymbols = new HashMap<>(); + ArrayList rootSymbols = new ArrayList<>(); + Iterator itr = getAllContents(resource); + while (itr.hasNext()) { + operationCanceledManager.checkCanceled(cancelIndicator); + Optional next = toEObject(itr.next()); + if (next.isPresent()) { + EObject object = next.get(); + DocumentSymbol symbol = symbolMapper.toDocumentSymbol(object); + if (isValid(symbol)) { + allSymbols.put(object, symbol); + EObject parent = object.eContainer(); + if (parent == null) { + rootSymbols.add(symbol); + } else { + DocumentSymbol parentSymbol = allSymbols.get(parent); + while (parentSymbol == null && parent != null) { + parent = parent.eContainer(); + parentSymbol = allSymbols.get(parent); + } + if (parentSymbol == null) { + rootSymbols.add(symbol); + } else { + parentSymbol.getChildren().add(symbol); + } + } + } + } + } + return rootSymbols.stream().map(symbol -> Either.forRight(symbol)) + .collect(Collectors.toList()); + } + + protected Iterator getAllContents(Resource resource) { + return EcoreUtil.getAllProperContents(resource, true); + } + + protected Optional toEObject(Object object) { + if (object instanceof EObject) { + return Optional.of((EObject) object); + } + return Optional.absent(); + } +} diff --git a/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/symbol/HierarchicalDocumentSymbolService.xtend b/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/symbol/HierarchicalDocumentSymbolService.xtend deleted file mode 100644 index 6f8ab9ce65..0000000000 --- a/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/symbol/HierarchicalDocumentSymbolService.xtend +++ /dev/null @@ -1,107 +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.server.symbol - -import com.google.common.annotations.Beta -import com.google.common.base.Optional -import com.google.inject.Inject -import com.google.inject.Singleton -import java.util.Iterator -import org.eclipse.emf.ecore.EObject -import org.eclipse.emf.ecore.resource.Resource -import org.eclipse.emf.ecore.util.EcoreUtil -import org.eclipse.lsp4j.DocumentSymbol -import org.eclipse.lsp4j.DocumentSymbolParams -import org.eclipse.lsp4j.SymbolInformation -import org.eclipse.lsp4j.jsonrpc.messages.Either -import org.eclipse.lsp4j.jsonrpc.validation.NonNull -import org.eclipse.xtext.ide.server.Document -import org.eclipse.xtext.resource.XtextResource -import org.eclipse.xtext.service.OperationCanceledManager -import org.eclipse.xtext.util.CancelIndicator - -/** - * Document symbol service that is comply with the LSP 3.10.0 - * version. Unlike the {@link DocumentSymbolService}, this service can provide hierarchical document symbols. - */ -@Beta -@Singleton -class HierarchicalDocumentSymbolService implements IDocumentSymbolService { - - @Inject - DocumentSymbolMapper symbolMapper; - - @Inject - OperationCanceledManager operationCanceledManager; - - /** - * {@code false} if the argument is {@code null} or any of the {@link NonNull} properties - * are {@code null}. Otherwise, {@code true}. - */ - static def boolean isValid(DocumentSymbol symbol) { - return symbol !== null && !DocumentSymbol.declaredFields - .filter[annotations.exists[annotationType === NonNull]] - .map[accessible = true; it] - .map[get(symbol)] - .exists[it === null]; - } - - override getSymbols(Document document, XtextResource resource, DocumentSymbolParams params, - CancelIndicator cancelIndicator) { - - return getSymbols(resource, cancelIndicator); - } - - def getSymbols(XtextResource resource, CancelIndicator cancelIndicator) { - val allSymbols = newHashMap; - val rootSymbols = newArrayList; - val itr = getAllContents(resource); - while (itr.hasNext) { - operationCanceledManager.checkCanceled(cancelIndicator); - val next = itr.next.toEObject; - if (next.present) { - val object = next.get; - val symbol = symbolMapper.toDocumentSymbol(object); - if (symbol.valid) { - allSymbols.put(object, symbol); - var parent = object.eContainer; - if (parent === null) { - rootSymbols.add(symbol); - } else { - var parentSymbol = allSymbols.get(parent); - // Find the parent symbol and hook the current one to the parent. - while (parentSymbol === null && parent !== null) { - parent = parent.eContainer; - parentSymbol = allSymbols.get(parent); - } - // If there parent cannot be found, it is a root. - if (parentSymbol === null) { - rootSymbols.add(symbol); - } else { - parentSymbol.children.add(symbol); - } - } - } - } - } - return rootSymbols.map[Either.forRight(it)]; - } - - protected def Iterator getAllContents(Resource resource) { - return EcoreUtil.getAllProperContents(resource, true); - } - - protected def Optional toEObject(Object object) { - if (object instanceof EObject) { - return Optional.of(object); - } - return Optional.absent; - } - -} diff --git a/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/server/contentassist/ContentAssistService.java b/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/server/contentassist/ContentAssistService.java deleted file mode 100644 index cecfb9933a..0000000000 --- a/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/server/contentassist/ContentAssistService.java +++ /dev/null @@ -1,283 +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.server.contentassist; - -import com.google.common.base.Objects; -import com.google.common.base.Strings; -import com.google.inject.Inject; -import com.google.inject.Provider; -import com.google.inject.Singleton; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.function.Consumer; -import org.eclipse.lsp4j.CompletionItem; -import org.eclipse.lsp4j.CompletionItemKind; -import org.eclipse.lsp4j.CompletionList; -import org.eclipse.lsp4j.CompletionParams; -import org.eclipse.lsp4j.InsertTextFormat; -import org.eclipse.lsp4j.Position; -import org.eclipse.lsp4j.Range; -import org.eclipse.lsp4j.TextEdit; -import org.eclipse.xtext.ide.editor.contentassist.ContentAssistContext; -import org.eclipse.xtext.ide.editor.contentassist.ContentAssistEntry; -import org.eclipse.xtext.ide.editor.contentassist.IIdeContentProposalAcceptor; -import org.eclipse.xtext.ide.editor.contentassist.IdeContentProposalAcceptor; -import org.eclipse.xtext.ide.editor.contentassist.IdeContentProposalProvider; -import org.eclipse.xtext.ide.editor.contentassist.antlr.ContentAssistContextFactory; -import org.eclipse.xtext.ide.server.Document; -import org.eclipse.xtext.resource.XtextResource; -import org.eclipse.xtext.service.OperationCanceledManager; -import org.eclipse.xtext.util.CancelIndicator; -import org.eclipse.xtext.util.ReplaceRegion; -import org.eclipse.xtext.util.TextRegion; -import org.eclipse.xtext.xbase.lib.Conversions; -import org.eclipse.xtext.xbase.lib.Exceptions; -import org.eclipse.xtext.xbase.lib.IterableExtensions; -import org.eclipse.xtext.xbase.lib.Procedures.Procedure2; - -/** - * @author kosyakov - Initial contribution and API - * @author Dennis Huebner - additionalTextEdits support - * - * @since 2.11 - */ -@Singleton -@SuppressWarnings("all") -public class ContentAssistService { - public static final int DEFAULT_PROPOSALS_LIMIT = 1000; - - @Inject - private Provider contextFactoryProvider; - - @Inject - private ExecutorService executorService; - - @Inject - private IdeContentProposalProvider proposalProvider; - - @Inject - private Provider proposalAcceptorProvider; - - @Inject - private OperationCanceledManager operationCanceledManager; - - public CompletionList createCompletionList(final Document document, final XtextResource resource, final CompletionParams params, final CancelIndicator cancelIndicator) { - try { - final CompletionList result = new CompletionList(); - result.setIsIncomplete(true); - final IdeContentProposalAcceptor acceptor = this.proposalAcceptorProvider.get(); - final int caretOffset = document.getOffSet(params.getPosition()); - final Position caretPosition = params.getPosition(); - final TextRegion position = new TextRegion(caretOffset, 0); - try { - this.createProposals(document.getContents(), position, caretOffset, resource, acceptor); - } catch (final Throwable _t) { - if (_t instanceof Throwable) { - final Throwable t = (Throwable)_t; - boolean _isOperationCanceledException = this.operationCanceledManager.isOperationCanceledException(t); - boolean _not = (!_isOperationCanceledException); - if (_not) { - throw t; - } - } else { - throw Exceptions.sneakyThrow(_t); - } - } - final Procedure2 _function = (ContentAssistEntry it, Integer idx) -> { - final CompletionItem item = this.toCompletionItem(it, caretOffset, caretPosition, document); - item.setSortText(Strings.padStart(Integer.toString((idx).intValue()), 5, '0')); - List _items = result.getItems(); - _items.add(item); - }; - IterableExtensions.forEach(acceptor.getEntries(), _function); - return result; - } catch (Throwable _e) { - throw Exceptions.sneakyThrow(_e); - } - } - - protected void createProposals(final String document, final TextRegion selection, final int caretOffset, final XtextResource resource, final IIdeContentProposalAcceptor acceptor) { - int _length = document.length(); - boolean _greaterThan = (caretOffset > _length); - if (_greaterThan) { - return; - } - final ContentAssistContextFactory contextFactory = this.contextFactoryProvider.get(); - contextFactory.setPool(this.executorService); - final ContentAssistContext[] contexts = contextFactory.create(document, selection, caretOffset, resource); - this.proposalProvider.createProposals(((Collection)Conversions.doWrapArray(contexts)), acceptor); - } - - protected CompletionItem toCompletionItem(final ContentAssistEntry entry, final int caretOffset, final Position caretPosition, final Document document) { - final CompletionItem completionItem = new CompletionItem(); - String _elvis = null; - String _label = entry.getLabel(); - if (_label != null) { - _elvis = _label; - } else { - String _proposal = entry.getProposal(); - _elvis = _proposal; - } - completionItem.setLabel(_elvis); - completionItem.setDetail(entry.getDescription()); - completionItem.setDocumentation(entry.getDocumentation()); - String _elvis_1 = null; - String _prefix = entry.getPrefix(); - if (_prefix != null) { - _elvis_1 = _prefix; - } else { - _elvis_1 = ""; - } - int _length = _elvis_1.length(); - final int prefixOffset = (caretOffset - _length); - final Position prefixPosition = document.getPosition(prefixOffset); - Range _range = new Range(prefixPosition, caretPosition); - String _proposal_1 = entry.getProposal(); - TextEdit _textEdit = new TextEdit(_range, _proposal_1); - completionItem.setTextEdit(_textEdit); - completionItem.setKind(this.translateKind(entry)); - boolean _isEmpty = entry.getTextReplacements().isEmpty(); - boolean _not = (!_isEmpty); - if (_not) { - List _additionalTextEdits = completionItem.getAdditionalTextEdits(); - boolean _tripleEquals = (_additionalTextEdits == null); - if (_tripleEquals) { - int _size = entry.getTextReplacements().size(); - ArrayList _arrayList = new ArrayList(_size); - completionItem.setAdditionalTextEdits(_arrayList); - } - final Consumer _function = (ReplaceRegion it) -> { - List _additionalTextEdits_1 = completionItem.getAdditionalTextEdits(); - TextEdit _textEdit_1 = this.toTextEdit(it, document); - _additionalTextEdits_1.add(_textEdit_1); - }; - entry.getTextReplacements().forEach(_function); - } - String _kind = entry.getKind(); - boolean _equals = Objects.equal(_kind, ContentAssistEntry.KIND_SNIPPET); - if (_equals) { - completionItem.setInsertTextFormat(InsertTextFormat.Snippet); - } - return completionItem; - } - - protected CompletionItemKind translateKind(final ContentAssistEntry entry) { - CompletionItemKind _switchResult = null; - String _kind = entry.getKind(); - if (_kind != null) { - switch (_kind) { - case ContentAssistEntry.KIND_CLASS: - _switchResult = CompletionItemKind.Class; - break; - case ContentAssistEntry.KIND_COLOR: - _switchResult = CompletionItemKind.Color; - break; - case ContentAssistEntry.KIND_CONSTRUCTOR: - _switchResult = CompletionItemKind.Constructor; - break; - case ContentAssistEntry.KIND_ENUM: - _switchResult = CompletionItemKind.Enum; - break; - case ContentAssistEntry.KIND_FIELD: - _switchResult = CompletionItemKind.Field; - break; - case ContentAssistEntry.KIND_FILE: - _switchResult = CompletionItemKind.File; - break; - case ContentAssistEntry.KIND_FUNCTION: - _switchResult = CompletionItemKind.Function; - break; - case ContentAssistEntry.KIND_INTERFACE: - _switchResult = CompletionItemKind.Interface; - break; - case ContentAssistEntry.KIND_KEYWORD: - _switchResult = CompletionItemKind.Keyword; - break; - case ContentAssistEntry.KIND_METHOD: - _switchResult = CompletionItemKind.Method; - break; - case ContentAssistEntry.KIND_MODULE: - _switchResult = CompletionItemKind.Module; - break; - case ContentAssistEntry.KIND_PROPERTY: - _switchResult = CompletionItemKind.Property; - break; - case ContentAssistEntry.KIND_REFERENCE: - _switchResult = CompletionItemKind.Reference; - break; - case ContentAssistEntry.KIND_SNIPPET: - _switchResult = CompletionItemKind.Snippet; - break; - case ContentAssistEntry.KIND_TEXT: - _switchResult = CompletionItemKind.Text; - break; - case ContentAssistEntry.KIND_UNIT: - _switchResult = CompletionItemKind.Unit; - break; - case ContentAssistEntry.KIND_VALUE: - _switchResult = CompletionItemKind.Value; - break; - case ContentAssistEntry.KIND_VARIABLE: - _switchResult = CompletionItemKind.Variable; - break; - default: - _switchResult = CompletionItemKind.Value; - break; - } - } else { - _switchResult = CompletionItemKind.Value; - } - return _switchResult; - } - - protected TextEdit toTextEdit(final ReplaceRegion region, final Document doc) { - TextEdit _xblockexpression = null; - { - Position _xifexpression = null; - int _offset = region.getOffset(); - int _length = doc.getContents().length(); - boolean _greaterThan = (_offset > _length); - if (_greaterThan) { - Position _xblockexpression_1 = null; - { - final Position docEnd = doc.getPosition(doc.getContents().length()); - int _line = docEnd.getLine(); - int _character = docEnd.getCharacter(); - int _length_1 = region.getLength(); - int _plus = (_character + _length_1); - _xblockexpression_1 = new Position(_line, _plus); - } - _xifexpression = _xblockexpression_1; - } else { - _xifexpression = doc.getPosition(region.getOffset()); - } - final Position start = _xifexpression; - Position _xifexpression_1 = null; - int _endOffset = region.getEndOffset(); - int _length_1 = doc.getContents().length(); - boolean _greaterThan_1 = (_endOffset > _length_1); - if (_greaterThan_1) { - int _line = start.getLine(); - int _character = start.getCharacter(); - int _length_2 = region.getLength(); - int _plus = (_character + _length_2); - _xifexpression_1 = new Position(_line, _plus); - } else { - _xifexpression_1 = doc.getPosition(region.getEndOffset()); - } - final Position end = _xifexpression_1; - Range _range = new Range(start, end); - String _text = region.getText(); - _xblockexpression = new TextEdit(_range, _text); - } - return _xblockexpression; - } -} diff --git a/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/server/rename/ChangeConverter2.java b/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/server/rename/ChangeConverter2.java deleted file mode 100644 index 9a199d5ec9..0000000000 --- a/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/server/rename/ChangeConverter2.java +++ /dev/null @@ -1,239 +0,0 @@ -/** - * Copyright (c) 2019 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.server.rename; - -import com.google.inject.Inject; -import java.io.ByteArrayOutputStream; -import java.nio.charset.Charset; -import java.util.Arrays; -import java.util.List; -import java.util.function.Function; -import org.eclipse.emf.ecore.resource.Resource; -import org.eclipse.emf.ecore.xmi.XMLResource; -import org.eclipse.lsp4j.ClientCapabilities; -import org.eclipse.lsp4j.InitializeParams; -import org.eclipse.lsp4j.Position; -import org.eclipse.lsp4j.Range; -import org.eclipse.lsp4j.ResourceOperation; -import org.eclipse.lsp4j.TextDocumentEdit; -import org.eclipse.lsp4j.TextEdit; -import org.eclipse.lsp4j.VersionedTextDocumentIdentifier; -import org.eclipse.lsp4j.WorkspaceClientCapabilities; -import org.eclipse.lsp4j.WorkspaceEdit; -import org.eclipse.lsp4j.WorkspaceEditCapabilities; -import org.eclipse.lsp4j.jsonrpc.messages.Either; -import org.eclipse.xtext.formatting2.regionaccess.ITextReplacement; -import org.eclipse.xtext.ide.serializer.IEmfResourceChange; -import org.eclipse.xtext.ide.serializer.ITextDocumentChange; -import org.eclipse.xtext.ide.server.Document; -import org.eclipse.xtext.ide.server.ILanguageServerAccess; -import org.eclipse.xtext.ide.server.UriExtensions; -import org.eclipse.xtext.parser.IEncodingProvider; -import org.eclipse.xtext.resource.IResourceServiceProvider; -import org.eclipse.xtext.util.IAcceptor; -import org.eclipse.xtext.xbase.lib.CollectionLiterals; -import org.eclipse.xtext.xbase.lib.Conversions; -import org.eclipse.xtext.xbase.lib.Exceptions; -import org.eclipse.xtext.xbase.lib.Extension; -import org.eclipse.xtext.xbase.lib.Functions.Function1; -import org.eclipse.xtext.xbase.lib.ListExtensions; -import org.eclipse.xtext.xbase.lib.ObjectExtensions; -import org.eclipse.xtext.xbase.lib.Procedures.Procedure1; - -/** - * @author koehnlein - Initial contribution and API - * @since 2.18 - */ -@SuppressWarnings("all") -public class ChangeConverter2 implements IAcceptor { - public static class Factory { - @Inject - protected IResourceServiceProvider.Registry registry; - - @Inject - protected UriExtensions uriExtensions; - - /** - * @since 2.18 - */ - public ChangeConverter2 create(final WorkspaceEdit edit, final ILanguageServerAccess access) { - return new ChangeConverter2(this.registry, edit, access, this.uriExtensions); - } - } - - private final IResourceServiceProvider.Registry registry; - - @Extension - private final UriExtensions uriExtensions; - - private final WorkspaceEdit edit; - - private final ILanguageServerAccess access; - - private final boolean useDocumentChanges; - - protected ChangeConverter2(final IResourceServiceProvider.Registry registry, final WorkspaceEdit edit, final ILanguageServerAccess access, final UriExtensions uriExtensions) { - this.registry = registry; - this.uriExtensions = uriExtensions; - this.edit = edit; - this.access = access; - InitializeParams _initializeParams = null; - if (access!=null) { - _initializeParams=access.getInitializeParams(); - } - ClientCapabilities _capabilities = null; - if (_initializeParams!=null) { - _capabilities=_initializeParams.getCapabilities(); - } - WorkspaceClientCapabilities _workspace = null; - if (_capabilities!=null) { - _workspace=_capabilities.getWorkspace(); - } - WorkspaceEditCapabilities _workspaceEdit = null; - if (_workspace!=null) { - _workspaceEdit=_workspace.getWorkspaceEdit(); - } - Boolean _documentChanges = null; - if (_workspaceEdit!=null) { - _documentChanges=_workspaceEdit.getDocumentChanges(); - } - boolean _tripleEquals = (_documentChanges == Boolean.TRUE); - this.useDocumentChanges = _tripleEquals; - if (this.useDocumentChanges) { - this.edit.setDocumentChanges(CollectionLiterals.>newArrayList()); - } else { - this.edit.setChanges(CollectionLiterals.>newLinkedHashMap()); - } - } - - @Override - public void accept(final IEmfResourceChange change) { - this.handleReplacements(change); - } - - protected void _handleReplacements(final IEmfResourceChange change) { - try { - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - final String uri = this.uriExtensions.toUriString(change.getResource().getURI()); - change.getResource().save(outputStream, null); - byte[] _byteArray = outputStream.toByteArray(); - String _charset = this.getCharset(change.getResource()); - final String newContent = new String(_byteArray, _charset); - final Function _function = (ILanguageServerAccess.Context context) -> { - Object _xblockexpression = null; - { - final Document document = context.getDocument(); - Position _position = document.getPosition(0); - Position _position_1 = document.getPosition(document.getContents().length()); - final Range range = new Range(_position, _position_1); - final TextEdit textEdit = new TextEdit(range, newContent); - _xblockexpression = this.addTextEdit(uri, document, textEdit); - } - return _xblockexpression; - }; - this.access.doRead(uri, _function).get(); - } catch (Throwable _e) { - throw Exceptions.sneakyThrow(_e); - } - } - - protected String getCharset(final Resource resource) { - String _xblockexpression = null; - { - final IEncodingProvider xtextEncodingProvider = this.registry.getResourceServiceProvider(resource.getURI()).get(IEncodingProvider.class); - String _xifexpression = null; - if ((xtextEncodingProvider != null)) { - return xtextEncodingProvider.getEncoding(resource.getURI()); - } else { - String _xifexpression_1 = null; - if ((resource instanceof XMLResource)) { - _xifexpression_1 = ((XMLResource)resource).getEncoding(); - } else { - _xifexpression_1 = Charset.defaultCharset().toString(); - } - _xifexpression = _xifexpression_1; - } - _xblockexpression = _xifexpression; - } - return _xblockexpression; - } - - protected void _handleReplacements(final ITextDocumentChange change) { - try { - int _size = change.getReplacements().size(); - boolean _greaterThan = (_size > 0); - if (_greaterThan) { - final String uri = this.uriExtensions.toUriString(change.getNewURI()); - final Function _function = (ILanguageServerAccess.Context context) -> { - Object _xblockexpression = null; - { - final Document document = context.getDocument(); - final Function1 _function_1 = (ITextReplacement replacement) -> { - TextEdit _xblockexpression_1 = null; - { - final Position start = document.getPosition(replacement.getOffset()); - int _offset = replacement.getOffset(); - int _length = replacement.getLength(); - int _plus = (_offset + _length); - final Position end = document.getPosition(_plus); - final Range range = new Range(start, end); - String _replacementText = replacement.getReplacementText(); - _xblockexpression_1 = new TextEdit(range, _replacementText); - } - return _xblockexpression_1; - }; - final List textEdits = ListExtensions.map(change.getReplacements(), _function_1); - _xblockexpression = this.addTextEdit(uri, document, ((TextEdit[])Conversions.unwrapArray(textEdits, TextEdit.class))); - } - return _xblockexpression; - }; - this.access.doRead(uri, _function).get(); - } - } catch (Throwable _e) { - throw Exceptions.sneakyThrow(_e); - } - } - - protected Object addTextEdit(final String theUri, final Document document, final TextEdit... textEdits) { - Object _xifexpression = null; - if (this.useDocumentChanges) { - List> _documentChanges = this.edit.getDocumentChanges(); - TextDocumentEdit _textDocumentEdit = new TextDocumentEdit(); - final Procedure1 _function = (TextDocumentEdit it) -> { - VersionedTextDocumentIdentifier _versionedTextDocumentIdentifier = new VersionedTextDocumentIdentifier(); - final Procedure1 _function_1 = (VersionedTextDocumentIdentifier it_1) -> { - it_1.setUri(theUri); - it_1.setVersion(document.getVersion()); - }; - VersionedTextDocumentIdentifier _doubleArrow = ObjectExtensions.operator_doubleArrow(_versionedTextDocumentIdentifier, _function_1); - it.setTextDocument(_doubleArrow); - it.setEdits(((List)Conversions.doWrapArray(textEdits))); - }; - TextDocumentEdit _doubleArrow = ObjectExtensions.operator_doubleArrow(_textDocumentEdit, _function); - Either _forLeft = Either.forLeft(_doubleArrow); - _xifexpression = Boolean.valueOf(_documentChanges.add(_forLeft)); - } else { - _xifexpression = this.edit.getChanges().put(theUri, ((List)Conversions.doWrapArray(textEdits))); - } - return _xifexpression; - } - - protected void handleReplacements(final IEmfResourceChange change) { - if (change instanceof ITextDocumentChange) { - _handleReplacements((ITextDocumentChange)change); - return; - } else if (change != null) { - _handleReplacements(change); - return; - } else { - throw new IllegalArgumentException("Unhandled parameter types: " + - Arrays.asList(change).toString()); - } - } -} diff --git a/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/server/rename/RenameService2.java b/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/server/rename/RenameService2.java deleted file mode 100644 index 4aba700cf3..0000000000 --- a/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/server/rename/RenameService2.java +++ /dev/null @@ -1,455 +0,0 @@ -/** - * Copyright (c) 2019 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.server.rename; - -import com.google.common.base.Function; -import com.google.common.base.Objects; -import com.google.common.base.Throwables; -import com.google.inject.Inject; -import com.google.inject.Provider; -import java.io.FileNotFoundException; -import java.util.Collections; -import org.apache.log4j.Logger; -import org.eclipse.emf.common.util.URI; -import org.eclipse.emf.ecore.EAttribute; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.resource.Resource; -import org.eclipse.emf.ecore.resource.ResourceSet; -import org.eclipse.emf.ecore.util.EcoreUtil; -import org.eclipse.lsp4j.InitializeResult; -import org.eclipse.lsp4j.Position; -import org.eclipse.lsp4j.PrepareRenameParams; -import org.eclipse.lsp4j.PrepareRenameResult; -import org.eclipse.lsp4j.Range; -import org.eclipse.lsp4j.RenameOptions; -import org.eclipse.lsp4j.RenameParams; -import org.eclipse.lsp4j.ServerCapabilities; -import org.eclipse.lsp4j.TextDocumentIdentifier; -import org.eclipse.lsp4j.WorkspaceEdit; -import org.eclipse.lsp4j.jsonrpc.messages.Either; -import org.eclipse.lsp4j.util.Ranges; -import org.eclipse.xtend.lib.annotations.AccessorType; -import org.eclipse.xtend.lib.annotations.Accessors; -import org.eclipse.xtend2.lib.StringConcatenation; -import org.eclipse.xtext.CrossReference; -import org.eclipse.xtext.RuleCall; -import org.eclipse.xtext.conversion.IValueConverterService; -import org.eclipse.xtext.ide.refactoring.IRenameStrategy2; -import org.eclipse.xtext.ide.refactoring.RefactoringIssueAcceptor; -import org.eclipse.xtext.ide.refactoring.RenameChange; -import org.eclipse.xtext.ide.refactoring.RenameContext; -import org.eclipse.xtext.ide.serializer.IChangeSerializer; -import org.eclipse.xtext.ide.server.Document; -import org.eclipse.xtext.ide.server.ILanguageServerAccess; -import org.eclipse.xtext.ide.server.rename.ChangeConverter2; -import org.eclipse.xtext.ide.server.rename.IRenameService2; -import org.eclipse.xtext.ide.server.rename.ServerRefactoringIssueAcceptor; -import org.eclipse.xtext.linking.impl.LinkingHelper; -import org.eclipse.xtext.nodemodel.ICompositeNode; -import org.eclipse.xtext.nodemodel.ILeafNode; -import org.eclipse.xtext.nodemodel.util.NodeModelUtils; -import org.eclipse.xtext.parser.IParseResult; -import org.eclipse.xtext.parsetree.reconstr.impl.TokenUtil; -import org.eclipse.xtext.resource.EObjectAtOffsetHelper; -import org.eclipse.xtext.resource.IResourceServiceProvider; -import org.eclipse.xtext.resource.XtextResource; -import org.eclipse.xtext.util.CancelIndicator; -import org.eclipse.xtext.util.SimpleAttributeResolver; -import org.eclipse.xtext.util.Strings; -import org.eclipse.xtext.util.internal.Log; -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.Pure; -import org.eclipse.xtext.xbase.lib.StringExtensions; - -/** - * @author koehnlein - Initial contribution and API - * @since 2.18 - */ -@Log -@Accessors(AccessorType.PROTECTED_GETTER) -@SuppressWarnings("all") -public class RenameService2 implements IRenameService2 { - @Inject - @Extension - private EObjectAtOffsetHelper eObjectAtOffsetHelper; - - @Inject - private Provider issueProvider; - - @Inject - private IResourceServiceProvider.Registry serviceProviderRegistry; - - @Inject - private TokenUtil tokenUtil; - - @Inject - private IValueConverterService valueConverterService; - - @Inject - private LinkingHelper linkingHelper; - - private Function attributeResolver = SimpleAttributeResolver.newResolver(String.class, "name"); - - @Override - public WorkspaceEdit rename(final IRenameService2.Options options) { - try { - final TextDocumentIdentifier textDocument = options.getRenameParams().getTextDocument(); - final String uri = textDocument.getUri(); - final ServerRefactoringIssueAcceptor issueAcceptor = this.issueProvider.get(); - final boolean shouldPrepareRename = this.shouldPrepareRename(options.getLanguageServerAccess()); - final java.util.function.Function _function = (ILanguageServerAccess.Context context) -> { - if (shouldPrepareRename) { - String _uri = textDocument.getUri(); - final TextDocumentIdentifier identifier = new TextDocumentIdentifier(_uri); - final Position position = options.getRenameParams().getPosition(); - final PrepareRenameParams positionParams = new PrepareRenameParams(identifier, position); - final Resource resource = context.getResource(); - final Document document = context.getDocument(); - final CancelIndicator cancelIndicator = options.getCancelIndicator(); - final Either prepareRenameResult = this.doPrepareRename(resource, document, positionParams, cancelIndicator); - boolean _mayPerformRename = this.mayPerformRename(prepareRenameResult, options.getRenameParams()); - boolean _not = (!_mayPerformRename); - if (_not) { - return null; - } - } - final WorkspaceEdit workspaceEdit = new WorkspaceEdit(); - final ResourceSet resourceSet = options.getLanguageServerAccess().newLiveScopeResourceSet(context.getResource().getURI()); - final Resource xtextResource = resourceSet.getResource(context.getResource().getURI(), true); - if ((xtextResource instanceof XtextResource)) { - final Position position_1 = options.getRenameParams().getPosition(); - EObject element = null; - try { - element = this.getElementAtOffset(((XtextResource)xtextResource), context.getDocument(), position_1); - } catch (final Throwable _t) { - if (_t instanceof IndexOutOfBoundsException) { - StringConcatenation _builder = new StringConcatenation(); - _builder.append("Invalid document "); - String _positionFragment = this.toPositionFragment(position_1, uri); - _builder.append(_positionFragment); - issueAcceptor.add(RefactoringIssueAcceptor.Severity.FATAL, _builder.toString()); - } else { - throw Exceptions.sneakyThrow(_t); - } - } - if (((element == null) || element.eIsProxy())) { - StringConcatenation _builder = new StringConcatenation(); - _builder.append("No element found at "); - String _positionFragment = this.toPositionFragment(position_1, uri); - _builder.append(_positionFragment); - issueAcceptor.add(RefactoringIssueAcceptor.Severity.FATAL, _builder.toString()); - } else { - final IResourceServiceProvider services = this.serviceProviderRegistry.getResourceServiceProvider(element.eResource().getURI()); - final IChangeSerializer changeSerializer = services.get(IChangeSerializer.class); - String _newName = options.getRenameParams().getNewName(); - URI _uRI = EcoreUtil.getURI(element); - final RenameChange change = new RenameChange(_newName, _uRI); - final RenameContext renameContext = new RenameContext(Collections.unmodifiableList(CollectionLiterals.newArrayList(change)), resourceSet, changeSerializer, issueAcceptor); - final IRenameStrategy2 renameStrategy = services.get(IRenameStrategy2.class); - renameStrategy.applyRename(renameContext); - final ChangeConverter2.Factory converterFactory = services.get(ChangeConverter2.Factory.class); - final ChangeConverter2 changeConverter = converterFactory.create(workspaceEdit, options.getLanguageServerAccess()); - changeSerializer.applyModifications(changeConverter); - } - } else { - issueAcceptor.add(RefactoringIssueAcceptor.Severity.FATAL, "Loaded resource is not an XtextResource", context.getResource().getURI()); - } - issueAcceptor.checkSeverity(); - return workspaceEdit; - }; - final java.util.function.Function _function_1 = (Throwable exception) -> { - try { - final Throwable rootCause = Throwables.getRootCause(exception); - if ((rootCause instanceof FileNotFoundException)) { - if (shouldPrepareRename) { - return null; - } - } - throw exception; - } catch (Throwable _e) { - throw Exceptions.sneakyThrow(_e); - } - }; - return options.getLanguageServerAccess().doRead(uri, _function).exceptionally(_function_1).get(); - } catch (Throwable _e) { - throw Exceptions.sneakyThrow(_e); - } - } - - protected EObject getElementAtOffset(final XtextResource xtextResource, final Document document, final Position caretPosition) { - final int caretOffset = document.getOffSet(caretPosition); - EObject _elvis = null; - EObject _elementWithIdentifierAt = this.getElementWithIdentifierAt(xtextResource, caretOffset); - if (_elementWithIdentifierAt != null) { - _elvis = _elementWithIdentifierAt; - } else { - EObject _elementWithIdentifierAt_1 = this.getElementWithIdentifierAt(xtextResource, (caretOffset - 1)); - _elvis = _elementWithIdentifierAt_1; - } - return _elvis; - } - - protected EObject getElementWithIdentifierAt(final XtextResource xtextResource, final int offset) { - if ((offset >= 0)) { - IParseResult _parseResult = null; - if (xtextResource!=null) { - _parseResult=xtextResource.getParseResult(); - } - ICompositeNode _rootNode = null; - if (_parseResult!=null) { - _rootNode=_parseResult.getRootNode(); - } - final ICompositeNode rootNode = _rootNode; - if ((rootNode != null)) { - final ILeafNode leaf = NodeModelUtils.findLeafNodeAtOffset(rootNode, offset); - if (((leaf != null) && this.isIdentifier(leaf))) { - return this.eObjectAtOffsetHelper.resolveElementAt(xtextResource, offset); - } - } - } - return null; - } - - protected boolean isIdentifier(final ILeafNode leafNode) { - return (((leafNode.getGrammarElement() instanceof RuleCall) || (leafNode.getGrammarElement() instanceof CrossReference)) && (!this.tokenUtil.isWhitespaceOrCommentNode(leafNode))); - } - - @Override - public Either prepareRename(final IRenameService2.PrepareRenameOptions options) { - try { - final String uri = options.getParams().getTextDocument().getUri(); - final boolean shouldPrepareRename = this.shouldPrepareRename(options.getLanguageServerAccess()); - final java.util.function.Function> _function = (ILanguageServerAccess.Context context) -> { - if ((!shouldPrepareRename)) { - return null; - } - final Resource resource = context.getResource(); - final Document document = context.getDocument(); - final PrepareRenameParams params = options.getParams(); - final CancelIndicator cancelIndicator = options.getCancelIndicator(); - return this.doPrepareRename(resource, document, params, cancelIndicator); - }; - final java.util.function.Function> _function_1 = (Throwable exception) -> { - try { - final Throwable rootCause = Throwables.getRootCause(exception); - if ((rootCause instanceof FileNotFoundException)) { - if (shouldPrepareRename) { - return null; - } - } - throw exception; - } catch (Throwable _e) { - throw Exceptions.sneakyThrow(_e); - } - }; - return options.getLanguageServerAccess().>doRead(uri, _function).exceptionally(_function_1).get(); - } catch (Throwable _e) { - throw Exceptions.sneakyThrow(_e); - } - } - - protected Either doPrepareRename(final Resource resource, final Document document, final PrepareRenameParams params, final CancelIndicator cancelIndicator) { - final String uri = params.getTextDocument().getUri(); - if ((resource instanceof XtextResource)) { - IParseResult _parseResult = null; - if (((XtextResource)resource)!=null) { - _parseResult=((XtextResource)resource).getParseResult(); - } - ICompositeNode _rootNode = null; - if (_parseResult!=null) { - _rootNode=_parseResult.getRootNode(); - } - final ICompositeNode rootNode = _rootNode; - if ((rootNode == null)) { - StringConcatenation _builder = new StringConcatenation(); - _builder.append("Could not retrieve root node for resource. URI: "); - _builder.append(uri); - _builder.append("."); - RenameService2.LOG.trace(_builder); - return null; - } - final Position caretPosition = params.getPosition(); - try { - final int caretOffset = document.getOffSet(caretPosition); - EObject element = null; - int candidateOffset = caretOffset; - do { - { - element = this.getElementWithIdentifierAt(((XtextResource)resource), candidateOffset); - if (((element != null) && (!element.eIsProxy()))) { - final ILeafNode leaf = NodeModelUtils.findLeafNodeAtOffset(rootNode, candidateOffset); - if (((leaf != null) && this.isIdentifier(leaf))) { - final String convertedNameValue = this.getConvertedValue(leaf.getGrammarElement(), leaf); - final String elementName = this.getElementName(element); - if ((((!StringExtensions.isNullOrEmpty(convertedNameValue)) && (!StringExtensions.isNullOrEmpty(elementName))) && Objects.equal(convertedNameValue, elementName))) { - final Position start = document.getPosition(leaf.getOffset()); - final Position end = document.getPosition(leaf.getEndOffset()); - Range _range = new Range(start, end); - return Either.forLeft(_range); - } - } - } - candidateOffset = (candidateOffset - 1); - } - } while(((candidateOffset >= 0) && ((candidateOffset + 1) >= caretOffset))); - } catch (final Throwable _t) { - if (_t instanceof IndexOutOfBoundsException) { - StringConcatenation _builder_1 = new StringConcatenation(); - _builder_1.append("Invalid document "); - String _positionFragment = this.toPositionFragment(caretPosition, uri); - _builder_1.append(_positionFragment); - RenameService2.LOG.trace(_builder_1); - return null; - } else { - throw Exceptions.sneakyThrow(_t); - } - } - StringConcatenation _builder_1 = new StringConcatenation(); - _builder_1.append("No element found at "); - String _positionFragment = this.toPositionFragment(caretPosition, uri); - _builder_1.append(_positionFragment); - RenameService2.LOG.trace(_builder_1); - } else { - StringConcatenation _builder_2 = new StringConcatenation(); - _builder_2.append("Loaded resource is not an XtextResource. URI: "); - URI _uRI = resource.getURI(); - _builder_2.append(_uRI); - RenameService2.LOG.trace(_builder_2); - } - return null; - } - - protected String getConvertedValue(final EObject grammarElement, final ILeafNode leaf) { - try { - boolean _matched = false; - if (grammarElement instanceof RuleCall) { - _matched=true; - return this.valueConverterService.toValue(leaf.getText(), ((RuleCall)grammarElement).getRule().getName(), leaf).toString(); - } - if (!_matched) { - if (grammarElement instanceof CrossReference) { - _matched=true; - return this.linkingHelper.getCrossRefNodeAsString(leaf, true); - } - } - } catch (final Throwable _t) { - if (_t instanceof Exception) { - } else { - throw Exceptions.sneakyThrow(_t); - } - } - return leaf.getText(); - } - - /** - * If this method returns {@code false}, it is sure, that the rename operation will fail. - * There is no guarantee that it will succeed even if it returns {@code true}. - */ - protected boolean mayPerformRename(final Either prepareRenameResult, final RenameParams renameParams) { - return (((prepareRenameResult != null) && (prepareRenameResult.getLeft() != null)) && - Ranges.containsPosition(prepareRenameResult.getLeft(), renameParams.getPosition())); - } - - /** - * Tries to read the {@code name} {@link EAttribute} from the - * the given {@code element}. - * - * It never returns an empty string, but a {@code null} instead. - */ - protected String getElementName(final EObject element) { - if ((element == null)) { - return null; - } - final String name = this.attributeResolver.apply(element); - String _xifexpression = null; - boolean _isEmpty = Strings.isEmpty(name); - if (_isEmpty) { - _xifexpression = null; - } else { - _xifexpression = name; - } - return _xifexpression; - } - - private String toPositionFragment(final Position it, final String uri) { - StringConcatenation _builder = new StringConcatenation(); - _builder.append("position line: "); - int _line = it.getLine(); - _builder.append(_line); - _builder.append(" column: "); - int _character = it.getCharacter(); - _builder.append(_character); - _builder.append(" in resource: "); - _builder.append(uri); - return _builder.toString(); - } - - private boolean shouldPrepareRename(final ILanguageServerAccess access) { - InitializeResult _initializeResult = null; - if (access!=null) { - _initializeResult=access.getInitializeResult(); - } - ServerCapabilities _capabilities = null; - if (_initializeResult!=null) { - _capabilities=_initializeResult.getCapabilities(); - } - Either _renameProvider = null; - if (_capabilities!=null) { - _renameProvider=_capabilities.getRenameProvider(); - } - final Either provider = _renameProvider; - boolean _xifexpression = false; - if (((provider != null) && provider.isRight())) { - Boolean _prepareProvider = provider.getRight().getPrepareProvider(); - _xifexpression = Objects.equal(Boolean.TRUE, _prepareProvider); - } else { - _xifexpression = false; - } - return _xifexpression; - } - - private static final Logger LOG = Logger.getLogger(RenameService2.class); - - @Pure - protected EObjectAtOffsetHelper getEObjectAtOffsetHelper() { - return this.eObjectAtOffsetHelper; - } - - @Pure - protected Provider getIssueProvider() { - return this.issueProvider; - } - - @Pure - protected IResourceServiceProvider.Registry getServiceProviderRegistry() { - return this.serviceProviderRegistry; - } - - @Pure - protected TokenUtil getTokenUtil() { - return this.tokenUtil; - } - - @Pure - protected IValueConverterService getValueConverterService() { - return this.valueConverterService; - } - - @Pure - protected LinkingHelper getLinkingHelper() { - return this.linkingHelper; - } - - @Pure - protected Function getAttributeResolver() { - return this.attributeResolver; - } -} diff --git a/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/server/symbol/DocumentSymbolService.java b/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/server/symbol/DocumentSymbolService.java deleted file mode 100644 index b2df863982..0000000000 --- a/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/server/symbol/DocumentSymbolService.java +++ /dev/null @@ -1,369 +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.server.symbol; - -import com.google.common.collect.Iterables; -import com.google.common.graph.SuccessorsFunction; -import com.google.common.graph.Traverser; -import com.google.inject.Inject; -import com.google.inject.Provider; -import com.google.inject.Singleton; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.function.Consumer; -import org.eclipse.emf.common.util.URI; -import org.eclipse.emf.ecore.EClass; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.resource.ResourceSet; -import org.eclipse.lsp4j.DefinitionParams; -import org.eclipse.lsp4j.DocumentSymbol; -import org.eclipse.lsp4j.DocumentSymbolParams; -import org.eclipse.lsp4j.Location; -import org.eclipse.lsp4j.ReferenceParams; -import org.eclipse.lsp4j.SymbolInformation; -import org.eclipse.lsp4j.SymbolKind; -import org.eclipse.lsp4j.jsonrpc.messages.Either; -import org.eclipse.xtext.findReferences.IReferenceFinder; -import org.eclipse.xtext.findReferences.ReferenceAcceptor; -import org.eclipse.xtext.findReferences.TargetURICollector; -import org.eclipse.xtext.findReferences.TargetURIs; -import org.eclipse.xtext.ide.server.Document; -import org.eclipse.xtext.ide.server.DocumentExtensions; -import org.eclipse.xtext.ide.server.UriExtensions; -import org.eclipse.xtext.ide.server.symbol.HierarchicalDocumentSymbolService; -import org.eclipse.xtext.ide.server.symbol.IDocumentSymbolService; -import org.eclipse.xtext.ide.util.CancelIndicatorProgressMonitor; -import org.eclipse.xtext.naming.IQualifiedNameProvider; -import org.eclipse.xtext.naming.QualifiedName; -import org.eclipse.xtext.resource.EObjectAtOffsetHelper; -import org.eclipse.xtext.resource.IEObjectDescription; -import org.eclipse.xtext.resource.IReferenceDescription; -import org.eclipse.xtext.resource.IResourceDescription; -import org.eclipse.xtext.resource.IResourceDescriptions; -import org.eclipse.xtext.resource.IResourceServiceProvider; -import org.eclipse.xtext.resource.XtextResource; -import org.eclipse.xtext.service.OperationCanceledManager; -import org.eclipse.xtext.util.CancelIndicator; -import org.eclipse.xtext.util.IAcceptor; -import org.eclipse.xtext.util.concurrent.IUnitOfWork; -import org.eclipse.xtext.xbase.lib.CollectionLiterals; -import org.eclipse.xtext.xbase.lib.Extension; -import org.eclipse.xtext.xbase.lib.Functions.Function1; -import org.eclipse.xtext.xbase.lib.IterableExtensions; -import org.eclipse.xtext.xbase.lib.ListExtensions; -import org.eclipse.xtext.xbase.lib.ObjectExtensions; -import org.eclipse.xtext.xbase.lib.Procedures.Procedure1; - -/** - * @author kosyakov - Initial contribution and API - * @since 2.11 - */ -@Singleton -@SuppressWarnings("all") -public class DocumentSymbolService implements IDocumentSymbolService { - @Inject - @Extension - private UriExtensions _uriExtensions; - - @Inject - @Extension - private DocumentExtensions _documentExtensions; - - @Inject - @Extension - private EObjectAtOffsetHelper _eObjectAtOffsetHelper; - - @Inject - @Extension - private IQualifiedNameProvider _iQualifiedNameProvider; - - @Inject - private IReferenceFinder referenceFinder; - - @Inject - private TargetURICollector targetURICollector; - - @Inject - private Provider targetURIProvider; - - @Inject - private OperationCanceledManager operationCanceledManager; - - @Inject - private IResourceServiceProvider.Registry resourceServiceProviderRegistry; - - @Inject - private HierarchicalDocumentSymbolService hierarchicalDocumentSymbolService; - - /** - * @since 2.21 - */ - public List getDefinitions(final Document document, final XtextResource resource, final DefinitionParams params, final IReferenceFinder.IResourceAccess resourceAccess, final CancelIndicator cancelIndicator) { - final int offset = document.getOffSet(params.getPosition()); - return this.getDefinitions(resource, offset, resourceAccess, cancelIndicator); - } - - public List getDefinitions(final XtextResource resource, final int offset, final IReferenceFinder.IResourceAccess resourceAccess, final CancelIndicator cancelIndicator) { - final EObject element = this._eObjectAtOffsetHelper.resolveElementAt(resource, offset); - if ((element == null)) { - return CollectionLiterals.emptyList(); - } - final ArrayList locations = CollectionLiterals.newArrayList(); - final TargetURIs targetURIs = this.collectTargetURIs(element); - for (final URI targetURI : targetURIs) { - { - this.operationCanceledManager.checkCanceled(cancelIndicator); - final Procedure1 _function = (EObject obj) -> { - final Location location = this._documentExtensions.newLocation(obj); - if ((location != null)) { - locations.add(location); - } - }; - this.doRead(resourceAccess, targetURI, _function); - } - } - return locations; - } - - public List getReferences(final Document document, final XtextResource resource, final ReferenceParams params, final IReferenceFinder.IResourceAccess resourceAccess, final IResourceDescriptions indexData, final CancelIndicator cancelIndicator) { - final int offset = document.getOffSet(params.getPosition()); - List _xifexpression = null; - boolean _isIncludeDeclaration = params.getContext().isIncludeDeclaration(); - if (_isIncludeDeclaration) { - _xifexpression = this.getDefinitions(resource, offset, resourceAccess, cancelIndicator); - } else { - _xifexpression = CollectionLiterals.emptyList(); - } - final List definitions = _xifexpression; - final List references = this.getReferences(resource, offset, resourceAccess, indexData, cancelIndicator); - final Iterable result = Iterables.concat(definitions, references); - return IterableExtensions.toList(result); - } - - public List getReferences(final XtextResource resource, final int offset, final IReferenceFinder.IResourceAccess resourceAccess, final IResourceDescriptions indexData, final CancelIndicator cancelIndicator) { - final EObject element = this._eObjectAtOffsetHelper.resolveElementAt(resource, offset); - if ((element == null)) { - return CollectionLiterals.emptyList(); - } - final ArrayList locations = CollectionLiterals.newArrayList(); - final TargetURIs targetURIs = this.collectTargetURIs(element); - final IAcceptor _function = (IReferenceDescription reference) -> { - final Procedure1 _function_1 = (EObject obj) -> { - final Location location = this._documentExtensions.newLocation(obj, reference.getEReference(), reference.getIndexInList()); - if ((location != null)) { - locations.add(location); - } - }; - this.doRead(resourceAccess, reference.getSourceEObjectUri(), _function_1); - }; - ReferenceAcceptor _referenceAcceptor = new ReferenceAcceptor(this.resourceServiceProviderRegistry, _function); - CancelIndicatorProgressMonitor _cancelIndicatorProgressMonitor = new CancelIndicatorProgressMonitor(cancelIndicator); - this.referenceFinder.findAllReferences(targetURIs, resourceAccess, indexData, _referenceAcceptor, _cancelIndicatorProgressMonitor); - return locations; - } - - protected TargetURIs collectTargetURIs(final EObject targetObject) { - final TargetURIs targetURIs = this.targetURIProvider.get(); - this.targetURICollector.add(targetObject, targetURIs); - return targetURIs; - } - - @Override - public List> getSymbols(final Document document, final XtextResource resource, final DocumentSymbolParams params, final CancelIndicator cancelIndicator) { - return this.getSymbols(resource, cancelIndicator); - } - - public List> getSymbols(final XtextResource resource, final CancelIndicator cancelIndicator) { - final String uri = this._uriExtensions.toUriString(resource.getURI()); - final ArrayList infos = CollectionLiterals.newArrayList(); - final Function1, DocumentSymbol> _function = (Either it) -> { - return it.getRight(); - }; - final List rootSymbols = ListExtensions., DocumentSymbol>map(this.hierarchicalDocumentSymbolService.getSymbols(resource, cancelIndicator), _function); - final Consumer _function_1 = (DocumentSymbol rootSymbol) -> { - final SuccessorsFunction _function_2 = (DocumentSymbol it) -> { - return it.getChildren(); - }; - final Iterable symbols = Traverser.forTree(_function_2).depthFirstPreOrder(rootSymbol); - final Function1 _function_3 = (DocumentSymbol symbol) -> { - final Function1 _function_4 = (DocumentSymbol it) -> { - return Boolean.valueOf((((it != symbol) && (!IterableExtensions.isNullOrEmpty(it.getChildren()))) && it.getChildren().contains(symbol))); - }; - DocumentSymbol _findFirst = IterableExtensions.findFirst(symbols, _function_4); - String _name = null; - if (_findFirst!=null) { - _name=_findFirst.getName(); - } - return _name; - }; - final Function1 containerNameProvider = _function_3; - final Function1 _function_4 = (DocumentSymbol it) -> { - return this.createSymbol(uri, it, containerNameProvider); - }; - Iterables.addAll(infos, IterableExtensions.map(symbols, _function_4)); - }; - rootSymbols.forEach(_function_1); - final Function1> _function_2 = (SymbolInformation it) -> { - return Either.forLeft(it); - }; - return ListExtensions.>map(infos, _function_2); - } - - protected EObject getContainer(final EObject obj) { - return obj.eContainer(); - } - - /** - * @since 2.16 - */ - protected SymbolInformation createSymbol(final String uri, final DocumentSymbol symbol, final Function1 containerNameProvider) { - SymbolInformation _symbolInformation = new SymbolInformation(); - final Procedure1 _function = (SymbolInformation it) -> { - it.setName(symbol.getName()); - it.setKind(symbol.getKind()); - it.setDeprecated(symbol.getDeprecated()); - Location _location = new Location(); - final Procedure1 _function_1 = (Location it_1) -> { - it_1.setUri(uri); - it_1.setRange(symbol.getSelectionRange()); - }; - Location _doubleArrow = ObjectExtensions.operator_doubleArrow(_location, _function_1); - it.setLocation(_doubleArrow); - it.setContainerName(containerNameProvider.apply(symbol)); - }; - return ObjectExtensions.operator_doubleArrow(_symbolInformation, _function); - } - - protected SymbolInformation createSymbol(final EObject object) { - final String name = this.getSymbolName(object); - if ((name == null)) { - return null; - } - final SymbolKind kind = this.getSymbolKind(object); - if ((kind == null)) { - return null; - } - final Location location = this.getSymbolLocation(object); - if ((location == null)) { - return null; - } - final SymbolInformation symbol = new SymbolInformation(); - symbol.setName(name); - symbol.setKind(kind); - symbol.setLocation(location); - return symbol; - } - - protected String getSymbolName(final EObject object) { - return this.getSymbolName(this._iQualifiedNameProvider.getFullyQualifiedName(object)); - } - - protected SymbolKind getSymbolKind(final EObject object) { - return this.getSymbolKind(object.eClass()); - } - - protected Location getSymbolLocation(final EObject object) { - return this._documentExtensions.newLocation(object); - } - - public List getSymbols(final IResourceDescription resourceDescription, final String query, final IReferenceFinder.IResourceAccess resourceAccess, final CancelIndicator cancelIndicator) { - final LinkedList symbols = CollectionLiterals.newLinkedList(); - Iterable _exportedObjects = resourceDescription.getExportedObjects(); - for (final IEObjectDescription description : _exportedObjects) { - { - this.operationCanceledManager.checkCanceled(cancelIndicator); - boolean _filter = this.filter(description, query); - if (_filter) { - final Procedure1 _function = (SymbolInformation symbol) -> { - symbols.add(symbol); - }; - this.createSymbol(description, resourceAccess, _function); - } - } - } - return symbols; - } - - protected boolean filter(final IEObjectDescription description, final String query) { - return description.getQualifiedName().toLowerCase().toString().contains(query.toLowerCase()); - } - - protected void createSymbol(final IEObjectDescription description, final IReferenceFinder.IResourceAccess resourceAccess, final Procedure1 acceptor) { - final String name = this.getSymbolName(description); - if ((name == null)) { - return; - } - final SymbolKind kind = this.getSymbolKind(description); - if ((kind == null)) { - return; - } - final Procedure1 _function = (Location location) -> { - final SymbolInformation symbol = new SymbolInformation(name, kind, location); - acceptor.apply(symbol); - }; - this.getSymbolLocation(description, resourceAccess, _function); - } - - protected SymbolInformation createSymbol(final IEObjectDescription description) { - final String symbolName = this.getSymbolName(description); - if ((symbolName == null)) { - return null; - } - final SymbolKind symbolKind = this.getSymbolKind(description); - if ((symbolKind == null)) { - return null; - } - final SymbolInformation symbol = new SymbolInformation(); - symbol.setName(symbolName); - symbol.setKind(symbolKind); - return symbol; - } - - protected String getSymbolName(final IEObjectDescription description) { - return this.getSymbolName(description.getQualifiedName()); - } - - protected SymbolKind getSymbolKind(final IEObjectDescription description) { - return this.getSymbolKind(description.getEClass()); - } - - protected void getSymbolLocation(final IEObjectDescription description, final IReferenceFinder.IResourceAccess resourceAccess, final Procedure1 acceptor) { - final Procedure1 _function = (EObject obj) -> { - final Location location = this.getSymbolLocation(obj); - if ((location != null)) { - acceptor.apply(location); - } - }; - this.doRead(resourceAccess, description.getEObjectURI(), _function); - } - - protected String getSymbolName(final QualifiedName qualifiedName) { - String _string = null; - if (qualifiedName!=null) { - _string=qualifiedName.toString(); - } - return _string; - } - - protected SymbolKind getSymbolKind(final EClass type) { - return SymbolKind.Property; - } - - protected void doRead(final IReferenceFinder.IResourceAccess resourceAccess, final URI objectURI, final Procedure1 acceptor) { - final IUnitOfWork _function = (ResourceSet resourceSet) -> { - final EObject object = resourceSet.getEObject(objectURI, true); - if ((object != null)) { - acceptor.apply(object); - } - return null; - }; - resourceAccess.readOnly(objectURI, _function); - } -} diff --git a/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/server/symbol/HierarchicalDocumentSymbolService.java b/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/server/symbol/HierarchicalDocumentSymbolService.java deleted file mode 100644 index 5de3b4b81b..0000000000 --- a/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/server/symbol/HierarchicalDocumentSymbolService.java +++ /dev/null @@ -1,142 +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.server.symbol; - -import com.google.common.annotations.Beta; -import com.google.common.base.Optional; -import com.google.inject.Inject; -import com.google.inject.Singleton; -import java.lang.annotation.Annotation; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.resource.Resource; -import org.eclipse.emf.ecore.util.EcoreUtil; -import org.eclipse.lsp4j.DocumentSymbol; -import org.eclipse.lsp4j.DocumentSymbolParams; -import org.eclipse.lsp4j.SymbolInformation; -import org.eclipse.lsp4j.jsonrpc.messages.Either; -import org.eclipse.lsp4j.jsonrpc.validation.NonNull; -import org.eclipse.xtext.ide.server.Document; -import org.eclipse.xtext.ide.server.symbol.DocumentSymbolMapper; -import org.eclipse.xtext.ide.server.symbol.IDocumentSymbolService; -import org.eclipse.xtext.resource.XtextResource; -import org.eclipse.xtext.service.OperationCanceledManager; -import org.eclipse.xtext.util.CancelIndicator; -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.Functions.Function1; -import org.eclipse.xtext.xbase.lib.IterableExtensions; -import org.eclipse.xtext.xbase.lib.ListExtensions; - -/** - * Document symbol service that is comply with the LSP 3.10.0 - * version. Unlike the {@link DocumentSymbolService}, this service can provide hierarchical document symbols. - */ -@Beta -@Singleton -@SuppressWarnings("all") -public class HierarchicalDocumentSymbolService implements IDocumentSymbolService { - @Inject - private DocumentSymbolMapper symbolMapper; - - @Inject - private OperationCanceledManager operationCanceledManager; - - /** - * {@code false} if the argument is {@code null} or any of the {@link NonNull} properties - * are {@code null}. Otherwise, {@code true}. - */ - public static boolean isValid(final DocumentSymbol symbol) { - return ((symbol != null) && (!IterableExtensions.exists(IterableExtensions.map(IterableExtensions.map(IterableExtensions.filter(((Iterable)Conversions.doWrapArray(DocumentSymbol.class.getDeclaredFields())), ((Function1) (Field it) -> { - final Function1 _function = (Annotation it_1) -> { - Class _annotationType = it_1.annotationType(); - return Boolean.valueOf((_annotationType == NonNull.class)); - }; - return Boolean.valueOf(IterableExtensions.exists(((Iterable)Conversions.doWrapArray(it.getAnnotations())), _function)); - })), ((Function1) (Field it) -> { - Field _xblockexpression = null; - { - it.setAccessible(true); - _xblockexpression = it; - } - return _xblockexpression; - })), ((Function1) (Field it) -> { - try { - return it.get(symbol); - } catch (Throwable _e) { - throw Exceptions.sneakyThrow(_e); - } - })), ((Function1) (Object it) -> { - return Boolean.valueOf((it == null)); - })))); - } - - @Override - public List> getSymbols(final Document document, final XtextResource resource, final DocumentSymbolParams params, final CancelIndicator cancelIndicator) { - return this.getSymbols(resource, cancelIndicator); - } - - public List> getSymbols(final XtextResource resource, final CancelIndicator cancelIndicator) { - final HashMap allSymbols = CollectionLiterals.newHashMap(); - final ArrayList rootSymbols = CollectionLiterals.newArrayList(); - final Iterator itr = this.getAllContents(resource); - while (itr.hasNext()) { - { - this.operationCanceledManager.checkCanceled(cancelIndicator); - final Optional next = this.toEObject(itr.next()); - boolean _isPresent = next.isPresent(); - if (_isPresent) { - final EObject object = next.get(); - final DocumentSymbol symbol = this.symbolMapper.toDocumentSymbol(object); - boolean _isValid = HierarchicalDocumentSymbolService.isValid(symbol); - if (_isValid) { - allSymbols.put(object, symbol); - EObject parent = object.eContainer(); - if ((parent == null)) { - rootSymbols.add(symbol); - } else { - DocumentSymbol parentSymbol = allSymbols.get(parent); - while (((parentSymbol == null) && (parent != null))) { - { - parent = parent.eContainer(); - parentSymbol = allSymbols.get(parent); - } - } - if ((parentSymbol == null)) { - rootSymbols.add(symbol); - } else { - parentSymbol.getChildren().add(symbol); - } - } - } - } - } - } - final Function1> _function = (DocumentSymbol it) -> { - return Either.forRight(it); - }; - return ListExtensions.>map(rootSymbols, _function); - } - - protected Iterator getAllContents(final Resource resource) { - return EcoreUtil.getAllProperContents(resource, true); - } - - protected Optional toEObject(final Object object) { - if ((object instanceof EObject)) { - return Optional.of(((EObject)object)); - } - return Optional.absent(); - } -} diff --git a/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/CodeConfig.java b/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/CodeConfig.java new file mode 100644 index 0000000000..219f6caafd --- /dev/null +++ b/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/CodeConfig.java @@ -0,0 +1,171 @@ +/** + * 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.nio.charset.Charset; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.eclipse.xtext.util.Strings; +import org.eclipse.xtext.util.XtextVersion; +import org.eclipse.xtext.xtext.generator.model.TypeReference; +import org.eclipse.xtext.xtext.generator.model.annotations.IClassAnnotation; + +import com.google.inject.Injector; + +/** + * Configuration object for generated code. + */ +public class CodeConfig implements IGuiceAwareGeneratorComponent { + private static final String FILE_HEADER_VAR_TIME = "${time}"; + + private static final String FILE_HEADER_VAR_DATE = "${date}"; + + private static final String FILE_HEADER_VAR_YEAR = "${year}"; + + private static final String FILE_HEADER_VAR_USER = "${user}"; + + private static final String FILE_HEADER_VAR_VERSION = "${version}"; + + private String encoding = Charset.defaultCharset().name(); + + private String lineDelimiter = Strings.newLine(); + + private String fileHeader; + + private String fileHeaderTemplate = "/*\n * generated by Xtext\n */"; + + private final List classAnnotations = new ArrayList<>(); + + private boolean preferXtendStubs = true; + + private XtextVersion xtextVersion; + + /** + * Configure a template for file headers. The template can contain + * variables: + *
    + *
  • ${time} - the current time of the day + * (hour:minute:second)
  • + *
  • ${date} - the current date (month day, year)
  • + *
  • ${year} - the current year
  • + *
  • ${user} - the content of the 'user.name' system + * property
  • + *
  • ${version} - the generator bundle version
  • + *
+ */ + public void setFileHeader(String fileHeaderTemplate) { + this.fileHeaderTemplate = fileHeaderTemplate; + } + + /** + * Class annotations are used to configure specific Java annotations to be + * added to each generated class. + */ + public void addClassAnnotation(IClassAnnotation annotation) { + classAnnotations.add(annotation); + } + + @Override + public void initialize(Injector injector) { + injector.injectMembers(this); + xtextVersion = XtextVersion.getCurrent(); + if (lineDelimiter == null) { + lineDelimiter = "\n"; + } + String fileHeader = fileHeaderTemplate; + if (fileHeader != null) { + if (fileHeader.contains(CodeConfig.FILE_HEADER_VAR_TIME)) { + String time = new SimpleDateFormat("HH:mm:ss").format(new Date()); + fileHeader = fileHeader.replace(CodeConfig.FILE_HEADER_VAR_TIME, time); + } + if (fileHeader.contains(CodeConfig.FILE_HEADER_VAR_DATE)) { + String date = new SimpleDateFormat("MMM d, yyyy").format(new Date()); + fileHeader = fileHeader.replace(CodeConfig.FILE_HEADER_VAR_DATE, date); + } + if (fileHeader.contains(CodeConfig.FILE_HEADER_VAR_YEAR)) { + String year = new SimpleDateFormat("yyyy").format(new Date()); + fileHeader = fileHeader.replace(CodeConfig.FILE_HEADER_VAR_YEAR, year); + } + if (fileHeader.contains(CodeConfig.FILE_HEADER_VAR_USER)) { + String user = System.getProperty("user.name"); + if (user != null) { + fileHeader = fileHeader.replace(CodeConfig.FILE_HEADER_VAR_USER, user); + } + } + if (fileHeader.contains(CodeConfig.FILE_HEADER_VAR_VERSION)) { + fileHeader = fileHeader.replace(CodeConfig.FILE_HEADER_VAR_VERSION, xtextVersion.toString()); + } + } + this.fileHeader = fileHeader; + } + + public String getClassAnnotationsAsString() { + if (classAnnotations.isEmpty()) { + return null; + } + StringBuilder stringBuilder = new StringBuilder(); + for (IClassAnnotation annotation : classAnnotations) { + stringBuilder.append(annotation.toString()).append(Strings.newLine()); + } + return stringBuilder.toString(); + } + + public String getAnnotationImportsAsString() { + if (classAnnotations.isEmpty()) { + return null; + } + StringBuilder stringBuilder = new StringBuilder(); + for (IClassAnnotation annotation : classAnnotations) { + TypeReference importString = annotation.getAnnotationImport(); + if ((importString != null)) { + stringBuilder.append("import ").append(importString).append(";").append(Strings.newLine()); + } + } + return stringBuilder.toString(); + } + + public String getEncoding() { + return encoding; + } + + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + public String getLineDelimiter() { + return lineDelimiter; + } + + public void setLineDelimiter(String lineDelimiter) { + this.lineDelimiter = lineDelimiter; + } + + public String getFileHeader() { + return fileHeader; + } + + public List getClassAnnotations() { + return classAnnotations; + } + + public boolean isPreferXtendStubs() { + return preferXtendStubs; + } + + public void setPreferXtendStubs(boolean preferXtendStubs) { + this.preferXtendStubs = preferXtendStubs; + } + + public XtextVersion getXtextVersion() { + return xtextVersion; + } +} diff --git a/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/CodeConfig.xtend b/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/CodeConfig.xtend deleted file mode 100644 index 04ad5fe8bb..0000000000 --- a/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/CodeConfig.xtend +++ /dev/null @@ -1,136 +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 - -import com.google.inject.Injector -import java.nio.charset.Charset -import java.text.SimpleDateFormat -import java.util.Date -import java.util.List -import org.eclipse.xtend.lib.annotations.Accessors -import org.eclipse.xtext.util.Strings -import org.eclipse.xtext.util.XtextVersion -import org.eclipse.xtext.xtext.generator.model.annotations.IClassAnnotation - -/** - * Configuration object for generated code. - */ -class CodeConfig implements IGuiceAwareGeneratorComponent { - - static val FILE_HEADER_VAR_TIME = '${time}' - static val FILE_HEADER_VAR_DATE = '${date}' - static val FILE_HEADER_VAR_YEAR = '${year}' - static val FILE_HEADER_VAR_USER = '${user}' - static val FILE_HEADER_VAR_VERSION = '${version}' - - @Accessors - String encoding = Charset.defaultCharset.name - - @Accessors - String lineDelimiter = Strings.newLine - - @Accessors(PUBLIC_GETTER) - String fileHeader - - String fileHeaderTemplate = "/*\n * generated by Xtext\n */" - - @Accessors(PUBLIC_GETTER) - val List classAnnotations = newArrayList - - @Accessors - boolean preferXtendStubs = true - - @Accessors(PUBLIC_GETTER) - XtextVersion xtextVersion - - /** - * Configure a template for file headers. The template can contain variables: - *
    - *
  • ${time} - the current time of the day (hour:minute:second)
  • - *
  • ${date} - the current date (month day, year)
  • - *
  • ${year} - the current year
  • - *
  • ${user} - the content of the 'user.name' system property
  • - *
  • ${version} - the generator bundle version
  • - *
- */ - def void setFileHeader(String fileHeaderTemplate) { - this.fileHeaderTemplate = fileHeaderTemplate - } - - /** - * Class annotations are used to configure specific Java annotations to be added to each generated class. - */ - def void addClassAnnotation(IClassAnnotation annotation) { - this.classAnnotations.add(annotation) - } - - override initialize(Injector injector) { - injector.injectMembers(this) - - xtextVersion = XtextVersion.current - if (lineDelimiter === null) - lineDelimiter = '\n' - - var fileHeader = fileHeaderTemplate - if (fileHeader !== null) { - if (fileHeader.contains(FILE_HEADER_VAR_TIME)) { - val dateFormat = new SimpleDateFormat('HH:mm:ss') - val time = dateFormat.format(new Date) - fileHeader = fileHeader.replace(FILE_HEADER_VAR_TIME, time) - } - if (fileHeader.contains(FILE_HEADER_VAR_DATE)) { - val dateFormat = new SimpleDateFormat('MMM d, yyyy') - val date = dateFormat.format(new Date) - fileHeader = fileHeader.replace(FILE_HEADER_VAR_DATE, date) - } - if (fileHeader.contains(FILE_HEADER_VAR_YEAR)) { - val dateFormat = new SimpleDateFormat('yyyy') - val year = dateFormat.format(new Date) - fileHeader = fileHeader.replace(FILE_HEADER_VAR_YEAR, year) - } - if (fileHeader.contains(FILE_HEADER_VAR_USER)) { - val user = System.getProperty("user.name") - if (user !== null) { - fileHeader = fileHeader.replace(FILE_HEADER_VAR_USER, user) - } - } - if (fileHeader.contains(FILE_HEADER_VAR_VERSION)) { - fileHeader = fileHeader.replace(FILE_HEADER_VAR_VERSION, xtextVersion.toString) - } - } - this.fileHeader = fileHeader - } - - - def String getClassAnnotationsAsString() { - if (classAnnotations.isEmpty) { - return null - } - val stringBuilder = new StringBuilder - for (annotation : classAnnotations) { - stringBuilder.append(annotation.toString).append(Strings.newLine) - } - return stringBuilder.toString - } - - def String getAnnotationImportsAsString() { - if (classAnnotations.isEmpty) { - return null - } - val stringBuilder = new StringBuilder - for (annotation : classAnnotations) { - val importString = annotation.annotationImport - if (importString !== null) { - stringBuilder.append('import ').append(importString).append(';').append(Strings.newLine) - } - } - return stringBuilder.toString - } - -} diff --git a/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/model/XtendFileAccess.java b/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/model/XtendFileAccess.java new file mode 100644 index 0000000000..ddacfce3d2 --- /dev/null +++ b/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/model/XtendFileAccess.java @@ -0,0 +1,45 @@ +/** + * 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; + +import java.util.Set; + +import org.eclipse.xtext.xtext.generator.CodeConfig; + +import com.google.common.collect.ImmutableSet; + +/** + * A utility class for generating Xtend files. + */ +public class XtendFileAccess extends JavaFileAccess { + /** + * A list of keywords in the Xtend language. Use this to avoid illegal + * variable names. + */ + public static final Set XTEND_KEYWORDS = ImmutableSet.of("abstract", "for", "new", "switch", "default", + "package", "synchronized", "boolean", "do", "if", "private", "this", "double", "implements", "protected", + "throw", "byte", "else", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", + "catch", "extends", "int", "short", "try", "char", "final", "interface", "static", "void", "class", + "finally", "long", "strictfp", "volatile", "float", "native", "super", "while", "val", "var", "def", + "override", "annotation", "extension", "create", "dispatch"); + + protected XtendFileAccess(TypeReference typeRef, CodeConfig codeConfig) { + super(typeRef, codeConfig); + } + + @Override + protected String getFileExtension() { + return "xtend"; + } + + @Override + protected boolean appendSemicolons() { + return false; + } +} diff --git a/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/model/XtendFileAccess.xtend b/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/model/XtendFileAccess.xtend deleted file mode 100644 index 4c02ae699b..0000000000 --- a/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/model/XtendFileAccess.xtend +++ /dev/null @@ -1,42 +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 - -import org.eclipse.xtext.xtext.generator.CodeConfig - -/** - * A utility class for generating Xtend files. - */ -class XtendFileAccess extends JavaFileAccess { - - /** - * A list of keywords in the Xtend language. Use this to avoid illegal variable names. - */ - public static val XTEND_KEYWORDS = #{ - 'abstract', 'for', 'new', 'switch', 'default', 'package', 'synchronized', 'boolean', - 'do', 'if', 'private', 'this', 'double', 'implements', 'protected', 'throw', 'byte', - 'else', 'import', 'public', 'throws', 'case', 'enum', 'instanceof', 'return', 'transient', - 'catch', 'extends', 'int', 'short', 'try', 'char', 'final', 'interface', 'static', - 'void', 'class', 'finally', 'long', 'strictfp', 'volatile', 'float', 'native', 'super', - 'while', 'val', 'var', 'def', 'override', 'annotation', 'extension', 'create', 'dispatch' - } - - protected new(TypeReference typeRef, CodeConfig codeConfig) { - super(typeRef, codeConfig) - } - - override protected getFileExtension() { - 'xtend' - } - - override protected appendSemicolons() { - false - } - -} diff --git a/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/model/project/XtextProjectConfig.java b/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/model/project/XtextProjectConfig.java new file mode 100644 index 0000000000..ce1579db70 --- /dev/null +++ b/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/model/project/XtextProjectConfig.java @@ -0,0 +1,156 @@ +/** + * 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 java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +import org.eclipse.xtext.xtext.generator.CodeConfig; +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.XtextGeneratorFileSystemAccess; + +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.inject.Injector; + +/** + * Configuration of the subprojects for one or more Xtext languages. If the + * standard project names and layout is sufficient, use + * {@link StandardProjectConfig}. + * + * @noextend This class should not be extended by clients. + */ +public class XtextProjectConfig implements IXtextProjectConfig { + private RuntimeProjectConfig runtime = new RuntimeProjectConfig(); + + private BundleProjectConfig runtimeTest = new BundleProjectConfig(); + + private BundleProjectConfig genericIde = new BundleProjectConfig(); + + private BundleProjectConfig eclipsePlugin = new BundleProjectConfig(); + + private BundleProjectConfig eclipsePluginTest = new BundleProjectConfig(); + + private WebProjectConfig web = new WebProjectConfig(); + + @Inject + private CodeConfig codeConfig; + + public void checkConfiguration(Issues issues) { + for (SubProjectConfig it : getEnabledProjects()) { + it.checkConfiguration(issues); + } + } + + public List getAllProjects() { + return Lists.newArrayList(runtime, runtimeTest, genericIde, eclipsePlugin, eclipsePluginTest, web); + } + + @Override + public List getTestProjects() { + return Lists.newArrayList(runtimeTest, eclipsePluginTest); + } + + @Override + public List getEnabledProjects() { + List enabledProjects = new ArrayList<>(); + Iterables.addAll(enabledProjects, Iterables.filter(getAllProjects(), SubProjectConfig::isEnabled)); + return enabledProjects; + } + + @Override + public void initialize(Injector injector) { + setDefaults(); + injector.injectMembers(this); + for (SubProjectConfig it : getEnabledProjects()) { + it.initialize(injector); + } + } + + public void setDefaults() { + runtime.setEnabled(true); + if (eclipsePlugin.isEnabled() || web.isEnabled()) { + genericIde.setEnabled(true); + } + } + + protected ManifestAccess newManifestAccess() { + ManifestAccess manifestAccess = new ManifestAccess(); + manifestAccess.setLineDelimiter(codeConfig.getLineDelimiter()); + return manifestAccess; + } + + protected PluginXmlAccess newPluginXmlAccess() { + return new PluginXmlAccess(); + } + + protected XtextGeneratorFileSystemAccess newFileSystemAccess(String path, boolean overWrite) { + return new XtextGeneratorFileSystemAccess(path, overWrite); + } + + public RuntimeProjectConfig getRuntime() { + return runtime; + } + + public void setRuntime(RuntimeProjectConfig runtime) { + this.runtime = runtime; + } + + public BundleProjectConfig getRuntimeTest() { + return runtimeTest; + } + + public void setRuntimeTest(BundleProjectConfig runtimeTest) { + this.runtimeTest = runtimeTest; + } + + public BundleProjectConfig getGenericIde() { + return genericIde; + } + + public void setGenericIde(BundleProjectConfig genericIde) { + this.genericIde = genericIde; + } + + public BundleProjectConfig getEclipsePlugin() { + return eclipsePlugin; + } + + public void setEclipsePlugin(BundleProjectConfig eclipsePlugin) { + this.eclipsePlugin = eclipsePlugin; + } + + public BundleProjectConfig getEclipsePluginTest() { + return eclipsePluginTest; + } + + public void setEclipsePluginTest(BundleProjectConfig eclipsePluginTest) { + this.eclipsePluginTest = eclipsePluginTest; + } + + public WebProjectConfig getWeb() { + return web; + } + + public void setWeb(WebProjectConfig web) { + this.web = web; + } + + public CodeConfig getCodeConfig() { + return codeConfig; + } + + public void setCodeConfig(CodeConfig codeConfig) { + this.codeConfig = codeConfig; + } +} diff --git a/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/model/project/XtextProjectConfig.xtend b/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/model/project/XtextProjectConfig.xtend deleted file mode 100644 index 7cf5c64881..0000000000 --- a/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/model/project/XtextProjectConfig.xtend +++ /dev/null @@ -1,100 +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.model.project - -import com.google.inject.Injector -import java.util.List -import javax.inject.Inject -import org.eclipse.xtend.lib.annotations.Accessors -import org.eclipse.xtext.xtext.generator.CodeConfig -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.XtextGeneratorFileSystemAccess - -/** - * Configuration of the subprojects for one or more Xtext languages. If the standard project names - * and layout is sufficient, use {@link StandardProjectConfig}. - * - * @noextend This class should not be extended by clients. - */ -@Accessors -class XtextProjectConfig implements IXtextProjectConfig { - - RuntimeProjectConfig runtime = new RuntimeProjectConfig - - BundleProjectConfig runtimeTest = new BundleProjectConfig - - BundleProjectConfig genericIde = new BundleProjectConfig - - BundleProjectConfig eclipsePlugin = new BundleProjectConfig - - BundleProjectConfig eclipsePluginTest = new BundleProjectConfig - - WebProjectConfig web = new WebProjectConfig - - @Inject CodeConfig codeConfig - - def void checkConfiguration(Issues issues) { - enabledProjects.forEach[checkConfiguration(issues)] - } - - def List getAllProjects() { - val allProjects = newArrayList - allProjects += #[ - runtime, - runtimeTest, - genericIde, - eclipsePlugin, - eclipsePluginTest, - web - ] - allProjects - } - - override List getTestProjects() { - val testProjects = newArrayList - testProjects += #[ - runtimeTest, - eclipsePluginTest - ] - testProjects - } - - override List getEnabledProjects() { - val enabledProjects = newArrayList - enabledProjects += allProjects.filter[enabled] - enabledProjects - } - - override initialize(Injector injector) { - setDefaults - injector.injectMembers(this) - enabledProjects.forEach[initialize(injector)] - } - - def setDefaults() { - runtime.enabled = true - if (#[eclipsePlugin, web].exists[enabled]) - genericIde.enabled = true - } - - protected def newManifestAccess() { - new ManifestAccess => [lineDelimiter = codeConfig.lineDelimiter] - } - - protected def newPluginXmlAccess() { - new PluginXmlAccess - } - - protected def newFileSystemAccess(String path, boolean overWrite) { - new XtextGeneratorFileSystemAccess(path, overWrite) - } - -} diff --git a/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/serializer/EqualAmbiguousTransitions.java b/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/serializer/EqualAmbiguousTransitions.java new file mode 100644 index 0000000000..5e34e2180d --- /dev/null +++ b/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/serializer/EqualAmbiguousTransitions.java @@ -0,0 +1,100 @@ +/** + * 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.serializer; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.xtext.AbstractElement; +import org.eclipse.xtext.grammaranalysis.impl.GrammarElementTitleSwitch; +import org.eclipse.xtext.serializer.analysis.GrammarAlias; +import org.eclipse.xtext.serializer.analysis.ISyntacticSequencerPDAProvider; +import org.eclipse.xtext.util.formallang.Production; +import org.eclipse.xtext.util.formallang.ProductionFormatter; +import org.eclipse.xtext.xbase.lib.IterableExtensions; + +import com.google.common.base.Objects; +import com.google.common.collect.Iterables; + +/** + * @author Moritz Eysholdt - Initial contribution and API + */ +public class EqualAmbiguousTransitions implements Comparable { + private final String identifier; + + private final List transitions = new ArrayList<>(); + + private final GrammarAlias.AbstractElementAlias elementAlias; + + public EqualAmbiguousTransitions(String identifier, GrammarAlias.AbstractElementAlias elementAlias) { + this.identifier = identifier; + this.elementAlias = elementAlias; + } + + public String getIdentifier() { + return identifier; + } + + public List getTransitions() { + return transitions; + } + + public GrammarAlias.AbstractElementAlias getElementAlias() { + return elementAlias; + } + + @Override + public int compareTo(EqualAmbiguousTransitions o) { + return identifier.compareTo(o.identifier); + } + + public String ambiguityInsideTransition(ISyntacticSequencerPDAProvider.ISynTransition trans) { + try { + GrammarElementTitleSwitch tokenToString = new GrammarElementTitleSwitch().showAssignments() + .hideCardinality().setValueForNull(""); + ProductionFormatter formatter = new ProductionFormatter() { + @Override + public String format(Production adapter, + GrammarAlias.AbstractElementAlias grammarElement, boolean needParenthesis) { + if (Objects.equal(grammarElement, elementAlias)) { + return "(ambiguity)"; + } + if (grammarElement instanceof GrammarAlias.TokenAlias) { + if (isStart((GrammarAlias.TokenAlias) grammarElement)) { + return "(rule start)"; + } + } + if (grammarElement instanceof GrammarAlias.TokenAlias) { + if (isStop((GrammarAlias.TokenAlias) grammarElement)) { + return "(rule end)"; + } + } + return super.format(adapter, grammarElement, needParenthesis); + } + }.setTokenToString(tokenToString).setAutoWrapChars(200).setAutoWrapChildren(20); + GrammarAlias.GrammarAliasAdapter adapter = new GrammarAlias.GrammarAliasAdapter(trans.getAmbiguousSyntax()); + return formatter.format(adapter, adapter.getRoot(), false); + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + } + + private boolean isStart(GrammarAlias.TokenAlias it) { + return (it.getToken() == null && it.getParent() instanceof GrammarAlias.GroupAlias && Objects.equal(it, + Iterables.getFirst(((GrammarAlias.GroupAlias) it.getParent()).getChildren(), null))); + } + + private boolean isStop(GrammarAlias.TokenAlias it) { + return (it.getToken() == null && it.getParent() instanceof GrammarAlias.GroupAlias + && Objects.equal(it, IterableExtensions.last( + ((GrammarAlias.GroupAlias) it.getParent()).getChildren()))); + } + +} diff --git a/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/serializer/EqualAmbiguousTransitions.xtend b/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/serializer/EqualAmbiguousTransitions.xtend deleted file mode 100644 index dc9a16b44a..0000000000 --- a/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/serializer/EqualAmbiguousTransitions.xtend +++ /dev/null @@ -1,69 +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.serializer - -import java.util.List -import org.eclipse.xtend.lib.annotations.Accessors -import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor -import org.eclipse.xtext.AbstractElement -import org.eclipse.xtext.grammaranalysis.impl.GrammarElementTitleSwitch -import org.eclipse.xtext.serializer.analysis.GrammarAlias.AbstractElementAlias -import org.eclipse.xtext.serializer.analysis.GrammarAlias.GrammarAliasAdapter -import org.eclipse.xtext.serializer.analysis.GrammarAlias.GroupAlias -import org.eclipse.xtext.serializer.analysis.GrammarAlias.TokenAlias -import org.eclipse.xtext.serializer.analysis.ISyntacticSequencerPDAProvider.ISynTransition -import org.eclipse.xtext.util.formallang.Production -import org.eclipse.xtext.util.formallang.ProductionFormatter - -/** - * @author Moritz Eysholdt - Initial contribution and API - */ -@Accessors -@FinalFieldsConstructor -class EqualAmbiguousTransitions implements Comparable { - - val String identifier - val List transitions = newArrayList() - val AbstractElementAlias elementAlias - - override compareTo(EqualAmbiguousTransitions o) { - identifier.compareTo(o.identifier) - } - - def String ambiguityInsideTransition(ISynTransition trans) { - try { - val tokenToString = new GrammarElementTitleSwitch().showAssignments().hideCardinality().setValueForNull(''); - val formatter = new ProductionFormatter() { - override format(Production adapter, - AbstractElementAlias grammarElement, boolean needParenthesis) { - switch (grammarElement) { - case grammarElement == elementAlias: return '(ambiguity)' - TokenAlias case grammarElement.isStart: return '(rule start)' - TokenAlias case grammarElement.isStop: return '(rule end)' - default: super.format(adapter, grammarElement, needParenthesis) - } - } - }.setTokenToString(tokenToString).setAutoWrapChars(200).setAutoWrapChildren(20) - val adapter = new GrammarAliasAdapter(trans.ambiguousSyntax) - return formatter.format(adapter, adapter.root, false); - } catch (Exception e) { - e.printStackTrace - return '' - } - } - - def private boolean isStart(TokenAlias it) { - token === null && parent instanceof GroupAlias && it == (parent as GroupAlias).children.head - } - - def private boolean isStop(TokenAlias it) { - token === null && parent instanceof GroupAlias && it == (parent as GroupAlias).children.last - } - -} diff --git a/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/types/TypesGeneratorFragment2.java b/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/types/TypesGeneratorFragment2.java new file mode 100644 index 0000000000..d0cbe7cae7 --- /dev/null +++ b/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/types/TypesGeneratorFragment2.java @@ -0,0 +1,71 @@ +/** + * 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.types; + +import static org.eclipse.xtext.xtext.generator.model.TypeReference.*; + +import java.util.Set; + +import org.eclipse.xtend.lib.annotations.AccessorType; +import org.eclipse.xtend.lib.annotations.Accessors; +import org.eclipse.xtext.scoping.IGlobalScopeProvider; +import org.eclipse.xtext.xtext.generator.AbstractXtextGeneratorFragment; +import org.eclipse.xtext.xtext.generator.model.GuiceModuleAccess; +import org.eclipse.xtext.xtext.generator.util.BooleanGeneratorOption; +import org.eclipse.xtext.xtext.generator.xbase.XbaseUsageDetector; + +import com.google.inject.Inject; + +public class TypesGeneratorFragment2 extends AbstractXtextGeneratorFragment { + @Inject + private XbaseUsageDetector xbaseUsageDetector; + + @Accessors(AccessorType.PUBLIC_GETTER) + private final BooleanGeneratorOption onlyEnabledIfGrammarIsUsed = new BooleanGeneratorOption(false); + + public void setOnlyEnabledIfGrammarIsUsed(boolean onlyEnabledIfGrammarIsUsed) { + this.onlyEnabledIfGrammarIsUsed.set(onlyEnabledIfGrammarIsUsed); + } + + @Override + public void generate() { + if (onlyEnabledIfGrammarIsUsed.get() && !xbaseUsageDetector.inheritsXtype(getLanguage().getGrammar())) { + return; + } + new GuiceModuleAccess.BindingFactory() + .addTypeToType(typeRef(IGlobalScopeProvider.class), + typeRef("org.eclipse.xtext.common.types.xtext.TypesAwareDefaultGlobalScopeProvider")) + .contributeTo(getLanguage().getRuntimeGenModule()); + getLanguage().getRuntimeGenModule() + .setSuperClass(typeRef("org.eclipse.xtext.common.types.DefaultCommonTypesRuntimeModule")); + new GuiceModuleAccess.BindingFactory() + .addTypeToType(typeRef("org.eclipse.xtext.ui.editor.contentassist.PrefixMatcher"), + typeRef("org.eclipse.xtext.ui.editor.contentassist.FQNPrefixMatcher")) + .contributeTo(getLanguage().getEclipsePluginGenModule()); + getLanguage().getEclipsePluginGenModule() + .setSuperClass(typeRef("org.eclipse.xtext.common.types.ui.DefaultCommonTypesUiModule")); + if (getProjectConfig().getRuntime().getManifest() != null) { + Set requiredBundles = getProjectConfig().getRuntime().getManifest().getRequiredBundles(); + requiredBundles.add("org.eclipse.xtext.common.types"); + requiredBundles.add("org.objectweb.asm;bundle-version=\"[8.0.1,8.1.0)\";resolution:=optional"); + } + if (getProjectConfig().getRuntimeTest().getManifest() != null) { + Set requiredBundles = getProjectConfig().getRuntimeTest().getManifest().getRequiredBundles(); + requiredBundles.add("org.objectweb.asm;bundle-version=\"[8.0.1,8.1.0)\";resolution:=optional"); + } + if (getProjectConfig().getEclipsePlugin().getManifest() != null) { + Set requiredBundles = getProjectConfig().getEclipsePlugin().getManifest().getRequiredBundles(); + requiredBundles.add("org.eclipse.xtext.common.types.ui"); + } + } + + public BooleanGeneratorOption getOnlyEnabledIfGrammarIsUsed() { + return onlyEnabledIfGrammarIsUsed; + } +} diff --git a/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/types/TypesGeneratorFragment2.xtend b/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/types/TypesGeneratorFragment2.xtend deleted file mode 100644 index 312b0bc484..0000000000 --- a/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/types/TypesGeneratorFragment2.xtend +++ /dev/null @@ -1,69 +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.types - -import com.google.inject.Inject -import org.eclipse.xtend.lib.annotations.Accessors -import org.eclipse.xtext.scoping.IGlobalScopeProvider -import org.eclipse.xtext.xtext.generator.AbstractXtextGeneratorFragment -import org.eclipse.xtext.xtext.generator.model.GuiceModuleAccess -import org.eclipse.xtext.xtext.generator.util.BooleanGeneratorOption -import org.eclipse.xtext.xtext.generator.xbase.XbaseUsageDetector - -import static extension org.eclipse.xtext.xtext.generator.model.TypeReference.* - -class TypesGeneratorFragment2 extends AbstractXtextGeneratorFragment { - - @Inject XbaseUsageDetector xbaseUsageDetector - - @Accessors(PUBLIC_GETTER) - val onlyEnabledIfGrammarIsUsed = new BooleanGeneratorOption(false) - - def void setOnlyEnabledIfGrammarIsUsed(boolean onlyEnabledIfGrammarIsUsed) { - this.onlyEnabledIfGrammarIsUsed.set(onlyEnabledIfGrammarIsUsed) - } - - override generate() { - if (onlyEnabledIfGrammarIsUsed.get && !xbaseUsageDetector.inheritsXtype(language.grammar)) { - return; - } - new GuiceModuleAccess.BindingFactory() - .addTypeToType(IGlobalScopeProvider.typeRef, - 'org.eclipse.xtext.common.types.xtext.TypesAwareDefaultGlobalScopeProvider'.typeRef) - .contributeTo(language.runtimeGenModule) - language.runtimeGenModule.superClass = 'org.eclipse.xtext.common.types.DefaultCommonTypesRuntimeModule'.typeRef - - new GuiceModuleAccess.BindingFactory() - // overrides binding from org.eclipse.xtext.xtext.generator.exporting.QualifiedNamesFragment2 - .addTypeToType("org.eclipse.xtext.ui.editor.contentassist.PrefixMatcher".typeRef, - 'org.eclipse.xtext.ui.editor.contentassist.FQNPrefixMatcher'.typeRef) - .contributeTo(language.eclipsePluginGenModule) - language.eclipsePluginGenModule.superClass = 'org.eclipse.xtext.common.types.ui.DefaultCommonTypesUiModule'.typeRef - - if (projectConfig.runtime.manifest !== null) { - projectConfig.runtime.manifest.requiredBundles.addAll( - 'org.eclipse.xtext.common.types', - 'org.objectweb.asm;bundle-version="[8.0.1,8.1.0)";resolution:=optional' - ) - } - - if (projectConfig.runtimeTest.manifest !== null) { - projectConfig.runtimeTest.manifest.requiredBundles.add( - 'org.objectweb.asm;bundle-version="[8.0.1,8.1.0)";resolution:=optional' - ) - } - - if (projectConfig.eclipsePlugin.manifest !== null) { - projectConfig.eclipsePlugin.manifest.requiredBundles.add( - 'org.eclipse.xtext.common.types.ui' - ) - } - } - -} \ No newline at end of file diff --git a/org.eclipse.xtext.xtext.generator/xtend-gen/org/eclipse/xtext/xtext/generator/CodeConfig.java b/org.eclipse.xtext.xtext.generator/xtend-gen/org/eclipse/xtext/xtext/generator/CodeConfig.java deleted file mode 100644 index 68019e32ab..0000000000 --- a/org.eclipse.xtext.xtext.generator/xtend-gen/org/eclipse/xtext/xtext/generator/CodeConfig.java +++ /dev/null @@ -1,197 +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; - -import com.google.inject.Injector; -import java.nio.charset.Charset; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.List; -import org.eclipse.xtend.lib.annotations.AccessorType; -import org.eclipse.xtend.lib.annotations.Accessors; -import org.eclipse.xtext.util.Strings; -import org.eclipse.xtext.util.XtextVersion; -import org.eclipse.xtext.xbase.lib.CollectionLiterals; -import org.eclipse.xtext.xbase.lib.Pure; -import org.eclipse.xtext.xtext.generator.IGuiceAwareGeneratorComponent; -import org.eclipse.xtext.xtext.generator.model.TypeReference; -import org.eclipse.xtext.xtext.generator.model.annotations.IClassAnnotation; - -/** - * Configuration object for generated code. - */ -@SuppressWarnings("all") -public class CodeConfig implements IGuiceAwareGeneratorComponent { - private static final String FILE_HEADER_VAR_TIME = "${time}"; - - private static final String FILE_HEADER_VAR_DATE = "${date}"; - - private static final String FILE_HEADER_VAR_YEAR = "${year}"; - - private static final String FILE_HEADER_VAR_USER = "${user}"; - - private static final String FILE_HEADER_VAR_VERSION = "${version}"; - - @Accessors - private String encoding = Charset.defaultCharset().name(); - - @Accessors - private String lineDelimiter = Strings.newLine(); - - @Accessors(AccessorType.PUBLIC_GETTER) - private String fileHeader; - - private String fileHeaderTemplate = "/*\n * generated by Xtext\n */"; - - @Accessors(AccessorType.PUBLIC_GETTER) - private final List classAnnotations = CollectionLiterals.newArrayList(); - - @Accessors - private boolean preferXtendStubs = true; - - @Accessors(AccessorType.PUBLIC_GETTER) - private XtextVersion xtextVersion; - - /** - * Configure a template for file headers. The template can contain variables: - *
    - *
  • ${time} - the current time of the day (hour:minute:second)
  • - *
  • ${date} - the current date (month day, year)
  • - *
  • ${year} - the current year
  • - *
  • ${user} - the content of the 'user.name' system property
  • - *
  • ${version} - the generator bundle version
  • - *
- */ - public void setFileHeader(final String fileHeaderTemplate) { - this.fileHeaderTemplate = fileHeaderTemplate; - } - - /** - * Class annotations are used to configure specific Java annotations to be added to each generated class. - */ - public void addClassAnnotation(final IClassAnnotation annotation) { - this.classAnnotations.add(annotation); - } - - @Override - public void initialize(final Injector injector) { - injector.injectMembers(this); - this.xtextVersion = XtextVersion.getCurrent(); - if ((this.lineDelimiter == null)) { - this.lineDelimiter = "\n"; - } - String fileHeader = this.fileHeaderTemplate; - if ((fileHeader != null)) { - boolean _contains = fileHeader.contains(CodeConfig.FILE_HEADER_VAR_TIME); - if (_contains) { - final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); - Date _date = new Date(); - final String time = dateFormat.format(_date); - fileHeader = fileHeader.replace(CodeConfig.FILE_HEADER_VAR_TIME, time); - } - boolean _contains_1 = fileHeader.contains(CodeConfig.FILE_HEADER_VAR_DATE); - if (_contains_1) { - final SimpleDateFormat dateFormat_1 = new SimpleDateFormat("MMM d, yyyy"); - Date _date_1 = new Date(); - final String date = dateFormat_1.format(_date_1); - fileHeader = fileHeader.replace(CodeConfig.FILE_HEADER_VAR_DATE, date); - } - boolean _contains_2 = fileHeader.contains(CodeConfig.FILE_HEADER_VAR_YEAR); - if (_contains_2) { - final SimpleDateFormat dateFormat_2 = new SimpleDateFormat("yyyy"); - Date _date_2 = new Date(); - final String year = dateFormat_2.format(_date_2); - fileHeader = fileHeader.replace(CodeConfig.FILE_HEADER_VAR_YEAR, year); - } - boolean _contains_3 = fileHeader.contains(CodeConfig.FILE_HEADER_VAR_USER); - if (_contains_3) { - final String user = System.getProperty("user.name"); - if ((user != null)) { - fileHeader = fileHeader.replace(CodeConfig.FILE_HEADER_VAR_USER, user); - } - } - boolean _contains_4 = fileHeader.contains(CodeConfig.FILE_HEADER_VAR_VERSION); - if (_contains_4) { - fileHeader = fileHeader.replace(CodeConfig.FILE_HEADER_VAR_VERSION, this.xtextVersion.toString()); - } - } - this.fileHeader = fileHeader; - } - - public String getClassAnnotationsAsString() { - boolean _isEmpty = this.classAnnotations.isEmpty(); - if (_isEmpty) { - return null; - } - final StringBuilder stringBuilder = new StringBuilder(); - for (final IClassAnnotation annotation : this.classAnnotations) { - stringBuilder.append(annotation.toString()).append(Strings.newLine()); - } - return stringBuilder.toString(); - } - - public String getAnnotationImportsAsString() { - boolean _isEmpty = this.classAnnotations.isEmpty(); - if (_isEmpty) { - return null; - } - final StringBuilder stringBuilder = new StringBuilder(); - for (final IClassAnnotation annotation : this.classAnnotations) { - { - final TypeReference importString = annotation.getAnnotationImport(); - if ((importString != null)) { - stringBuilder.append("import ").append(importString).append(";").append(Strings.newLine()); - } - } - } - return stringBuilder.toString(); - } - - @Pure - public String getEncoding() { - return this.encoding; - } - - public void setEncoding(final String encoding) { - this.encoding = encoding; - } - - @Pure - public String getLineDelimiter() { - return this.lineDelimiter; - } - - public void setLineDelimiter(final String lineDelimiter) { - this.lineDelimiter = lineDelimiter; - } - - @Pure - public String getFileHeader() { - return this.fileHeader; - } - - @Pure - public List getClassAnnotations() { - return this.classAnnotations; - } - - @Pure - public boolean isPreferXtendStubs() { - return this.preferXtendStubs; - } - - public void setPreferXtendStubs(final boolean preferXtendStubs) { - this.preferXtendStubs = preferXtendStubs; - } - - @Pure - public XtextVersion getXtextVersion() { - return this.xtextVersion; - } -} diff --git a/org.eclipse.xtext.xtext.generator/xtend-gen/org/eclipse/xtext/xtext/generator/model/XtendFileAccess.java b/org.eclipse.xtext.xtext.generator/xtend-gen/org/eclipse/xtext/xtext/generator/model/XtendFileAccess.java deleted file mode 100644 index 9a4d9b2a21..0000000000 --- a/org.eclipse.xtext.xtext.generator/xtend-gen/org/eclipse/xtext/xtext/generator/model/XtendFileAccess.java +++ /dev/null @@ -1,41 +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; - -import java.util.Collections; -import java.util.Set; -import org.eclipse.xtext.xbase.lib.CollectionLiterals; -import org.eclipse.xtext.xtext.generator.CodeConfig; -import org.eclipse.xtext.xtext.generator.model.JavaFileAccess; -import org.eclipse.xtext.xtext.generator.model.TypeReference; - -/** - * A utility class for generating Xtend files. - */ -@SuppressWarnings("all") -public class XtendFileAccess extends JavaFileAccess { - /** - * A list of keywords in the Xtend language. Use this to avoid illegal variable names. - */ - public static final Set XTEND_KEYWORDS = Collections.unmodifiableSet(CollectionLiterals.newHashSet("abstract", "for", "new", "switch", "default", "package", "synchronized", "boolean", "do", "if", "private", "this", "double", "implements", "protected", "throw", "byte", "else", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", "catch", "extends", "int", "short", "try", "char", "final", "interface", "static", "void", "class", "finally", "long", "strictfp", "volatile", "float", "native", "super", "while", "val", "var", "def", "override", "annotation", "extension", "create", "dispatch")); - - protected XtendFileAccess(final TypeReference typeRef, final CodeConfig codeConfig) { - super(typeRef, codeConfig); - } - - @Override - protected String getFileExtension() { - return "xtend"; - } - - @Override - protected boolean appendSemicolons() { - return false; - } -} diff --git a/org.eclipse.xtext.xtext.generator/xtend-gen/org/eclipse/xtext/xtext/generator/model/project/XtextProjectConfig.java b/org.eclipse.xtext.xtext.generator/xtend-gen/org/eclipse/xtext/xtext/generator/model/project/XtextProjectConfig.java deleted file mode 100644 index c0fe3f57ae..0000000000 --- a/org.eclipse.xtext.xtext.generator/xtend-gen/org/eclipse/xtext/xtext/generator/model/project/XtextProjectConfig.java +++ /dev/null @@ -1,202 +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.model.project; - -import com.google.common.collect.Iterables; -import com.google.inject.Injector; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.function.Consumer; -import javax.inject.Inject; -import org.eclipse.xtend.lib.annotations.Accessors; -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.ObjectExtensions; -import org.eclipse.xtext.xbase.lib.Procedures.Procedure1; -import org.eclipse.xtext.xbase.lib.Pure; -import org.eclipse.xtext.xtext.generator.CodeConfig; -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.XtextGeneratorFileSystemAccess; -import org.eclipse.xtext.xtext.generator.model.project.BundleProjectConfig; -import org.eclipse.xtext.xtext.generator.model.project.IXtextProjectConfig; -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; - -/** - * Configuration of the subprojects for one or more Xtext languages. If the standard project names - * and layout is sufficient, use {@link StandardProjectConfig}. - * - * @noextend This class should not be extended by clients. - */ -@Accessors -@SuppressWarnings("all") -public class XtextProjectConfig implements IXtextProjectConfig { - private RuntimeProjectConfig runtime = new RuntimeProjectConfig(); - - private BundleProjectConfig runtimeTest = new BundleProjectConfig(); - - private BundleProjectConfig genericIde = new BundleProjectConfig(); - - private BundleProjectConfig eclipsePlugin = new BundleProjectConfig(); - - private BundleProjectConfig eclipsePluginTest = new BundleProjectConfig(); - - private WebProjectConfig web = new WebProjectConfig(); - - @Inject - private CodeConfig codeConfig; - - public void checkConfiguration(final Issues issues) { - final Consumer _function = (SubProjectConfig it) -> { - it.checkConfiguration(issues); - }; - this.getEnabledProjects().forEach(_function); - } - - public List getAllProjects() { - ArrayList _xblockexpression = null; - { - final ArrayList allProjects = CollectionLiterals.newArrayList(); - Iterables.addAll(allProjects, Collections.unmodifiableList(CollectionLiterals.newArrayList(this.runtime, this.runtimeTest, this.genericIde, this.eclipsePlugin, this.eclipsePluginTest, this.web))); - _xblockexpression = allProjects; - } - return _xblockexpression; - } - - @Override - public List getTestProjects() { - ArrayList _xblockexpression = null; - { - final ArrayList testProjects = CollectionLiterals.newArrayList(); - Iterables.addAll(testProjects, Collections.unmodifiableList(CollectionLiterals.newArrayList(this.runtimeTest, this.eclipsePluginTest))); - _xblockexpression = testProjects; - } - return _xblockexpression; - } - - @Override - public List getEnabledProjects() { - ArrayList _xblockexpression = null; - { - final ArrayList enabledProjects = CollectionLiterals.newArrayList(); - final Function1 _function = (SubProjectConfig it) -> { - return Boolean.valueOf(it.isEnabled()); - }; - Iterable _filter = IterableExtensions.filter(this.getAllProjects(), _function); - Iterables.addAll(enabledProjects, _filter); - _xblockexpression = enabledProjects; - } - return _xblockexpression; - } - - @Override - public void initialize(final Injector injector) { - this.setDefaults(); - injector.injectMembers(this); - final Consumer _function = (SubProjectConfig it) -> { - it.initialize(injector); - }; - this.getEnabledProjects().forEach(_function); - } - - public void setDefaults() { - this.runtime.setEnabled(true); - final Function1 _function = (SubProjectConfig it) -> { - return Boolean.valueOf(it.isEnabled()); - }; - boolean _exists = IterableExtensions.exists(Collections.unmodifiableList(CollectionLiterals.newArrayList(this.eclipsePlugin, this.web)), _function); - if (_exists) { - this.genericIde.setEnabled(true); - } - } - - protected ManifestAccess newManifestAccess() { - ManifestAccess _manifestAccess = new ManifestAccess(); - final Procedure1 _function = (ManifestAccess it) -> { - it.setLineDelimiter(this.codeConfig.getLineDelimiter()); - }; - return ObjectExtensions.operator_doubleArrow(_manifestAccess, _function); - } - - protected PluginXmlAccess newPluginXmlAccess() { - return new PluginXmlAccess(); - } - - protected XtextGeneratorFileSystemAccess newFileSystemAccess(final String path, final boolean overWrite) { - return new XtextGeneratorFileSystemAccess(path, overWrite); - } - - @Pure - public RuntimeProjectConfig getRuntime() { - return this.runtime; - } - - public void setRuntime(final RuntimeProjectConfig runtime) { - this.runtime = runtime; - } - - @Pure - public BundleProjectConfig getRuntimeTest() { - return this.runtimeTest; - } - - public void setRuntimeTest(final BundleProjectConfig runtimeTest) { - this.runtimeTest = runtimeTest; - } - - @Pure - public BundleProjectConfig getGenericIde() { - return this.genericIde; - } - - public void setGenericIde(final BundleProjectConfig genericIde) { - this.genericIde = genericIde; - } - - @Pure - public BundleProjectConfig getEclipsePlugin() { - return this.eclipsePlugin; - } - - public void setEclipsePlugin(final BundleProjectConfig eclipsePlugin) { - this.eclipsePlugin = eclipsePlugin; - } - - @Pure - public BundleProjectConfig getEclipsePluginTest() { - return this.eclipsePluginTest; - } - - public void setEclipsePluginTest(final BundleProjectConfig eclipsePluginTest) { - this.eclipsePluginTest = eclipsePluginTest; - } - - @Pure - public WebProjectConfig getWeb() { - return this.web; - } - - public void setWeb(final WebProjectConfig web) { - this.web = web; - } - - @Pure - public CodeConfig getCodeConfig() { - return this.codeConfig; - } - - public void setCodeConfig(final CodeConfig codeConfig) { - this.codeConfig = codeConfig; - } -} diff --git a/org.eclipse.xtext.xtext.generator/xtend-gen/org/eclipse/xtext/xtext/generator/serializer/EqualAmbiguousTransitions.java b/org.eclipse.xtext.xtext.generator/xtend-gen/org/eclipse/xtext/xtext/generator/serializer/EqualAmbiguousTransitions.java deleted file mode 100644 index e5420010a3..0000000000 --- a/org.eclipse.xtext.xtext.generator/xtend-gen/org/eclipse/xtext/xtext/generator/serializer/EqualAmbiguousTransitions.java +++ /dev/null @@ -1,123 +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.serializer; - -import com.google.common.base.Objects; -import java.util.List; -import org.eclipse.xtend.lib.annotations.Accessors; -import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor; -import org.eclipse.xtext.AbstractElement; -import org.eclipse.xtext.grammaranalysis.impl.GrammarElementTitleSwitch; -import org.eclipse.xtext.serializer.analysis.GrammarAlias; -import org.eclipse.xtext.serializer.analysis.ISyntacticSequencerPDAProvider; -import org.eclipse.xtext.util.formallang.Production; -import org.eclipse.xtext.util.formallang.ProductionFormatter; -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.Pure; - -/** - * @author Moritz Eysholdt - Initial contribution and API - */ -@Accessors -@FinalFieldsConstructor -@SuppressWarnings("all") -public class EqualAmbiguousTransitions implements Comparable { - private final String identifier; - - private final List transitions = CollectionLiterals.newArrayList(); - - private final GrammarAlias.AbstractElementAlias elementAlias; - - @Override - public int compareTo(final EqualAmbiguousTransitions o) { - return this.identifier.compareTo(o.identifier); - } - - public String ambiguityInsideTransition(final ISyntacticSequencerPDAProvider.ISynTransition trans) { - try { - final GrammarElementTitleSwitch tokenToString = new GrammarElementTitleSwitch().showAssignments().hideCardinality().setValueForNull(""); - final ProductionFormatter formatter = new ProductionFormatter() { - @Override - public String format(final Production adapter, final GrammarAlias.AbstractElementAlias grammarElement, final boolean needParenthesis) { - String _switchResult = null; - boolean _matched = false; - boolean _equals = Objects.equal(grammarElement, EqualAmbiguousTransitions.this.elementAlias); - if (_equals) { - _matched=true; - return "(ambiguity)"; - } - if (!_matched) { - if (grammarElement instanceof GrammarAlias.TokenAlias) { - boolean _isStart = EqualAmbiguousTransitions.this.isStart(((GrammarAlias.TokenAlias)grammarElement)); - if (_isStart) { - _matched=true; - return "(rule start)"; - } - } - } - if (!_matched) { - if (grammarElement instanceof GrammarAlias.TokenAlias) { - boolean _isStop = EqualAmbiguousTransitions.this.isStop(((GrammarAlias.TokenAlias)grammarElement)); - if (_isStop) { - _matched=true; - return "(rule end)"; - } - } - } - if (!_matched) { - _switchResult = super.format(adapter, grammarElement, needParenthesis); - } - return _switchResult; - } - }.setTokenToString(tokenToString).setAutoWrapChars(200).setAutoWrapChildren(20); - GrammarAlias.AbstractElementAlias _ambiguousSyntax = trans.getAmbiguousSyntax(); - final GrammarAlias.GrammarAliasAdapter adapter = new GrammarAlias.GrammarAliasAdapter(_ambiguousSyntax); - return formatter.format(adapter, adapter.getRoot(), false); - } catch (final Throwable _t) { - if (_t instanceof Exception) { - final Exception e = (Exception)_t; - e.printStackTrace(); - return ""; - } else { - throw Exceptions.sneakyThrow(_t); - } - } - } - - private boolean isStart(final GrammarAlias.TokenAlias it) { - return (((it.getToken() == null) && (it.getParent() instanceof GrammarAlias.GroupAlias)) && Objects.equal(it, IterableExtensions.head(((GrammarAlias.GroupAlias) it.getParent()).getChildren()))); - } - - private boolean isStop(final GrammarAlias.TokenAlias it) { - return (((it.getToken() == null) && (it.getParent() instanceof GrammarAlias.GroupAlias)) && Objects.equal(it, IterableExtensions.last(((GrammarAlias.GroupAlias) it.getParent()).getChildren()))); - } - - public EqualAmbiguousTransitions(final String identifier, final GrammarAlias.AbstractElementAlias elementAlias) { - super(); - this.identifier = identifier; - this.elementAlias = elementAlias; - } - - @Pure - public String getIdentifier() { - return this.identifier; - } - - @Pure - public List getTransitions() { - return this.transitions; - } - - @Pure - public GrammarAlias.AbstractElementAlias getElementAlias() { - return this.elementAlias; - } -} diff --git a/org.eclipse.xtext.xtext.generator/xtend-gen/org/eclipse/xtext/xtext/generator/types/TypesGeneratorFragment2.java b/org.eclipse.xtext.xtext.generator/xtend-gen/org/eclipse/xtext/xtext/generator/types/TypesGeneratorFragment2.java deleted file mode 100644 index adc406de68..0000000000 --- a/org.eclipse.xtext.xtext.generator/xtend-gen/org/eclipse/xtext/xtext/generator/types/TypesGeneratorFragment2.java +++ /dev/null @@ -1,74 +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.types; - -import com.google.inject.Inject; -import org.eclipse.xtend.lib.annotations.AccessorType; -import org.eclipse.xtend.lib.annotations.Accessors; -import org.eclipse.xtext.scoping.IGlobalScopeProvider; -import org.eclipse.xtext.xbase.lib.CollectionExtensions; -import org.eclipse.xtext.xbase.lib.Pure; -import org.eclipse.xtext.xtext.generator.AbstractXtextGeneratorFragment; -import org.eclipse.xtext.xtext.generator.model.GuiceModuleAccess; -import org.eclipse.xtext.xtext.generator.model.ManifestAccess; -import org.eclipse.xtext.xtext.generator.model.TypeReference; -import org.eclipse.xtext.xtext.generator.util.BooleanGeneratorOption; -import org.eclipse.xtext.xtext.generator.xbase.XbaseUsageDetector; - -@SuppressWarnings("all") -public class TypesGeneratorFragment2 extends AbstractXtextGeneratorFragment { - @Inject - private XbaseUsageDetector xbaseUsageDetector; - - @Accessors(AccessorType.PUBLIC_GETTER) - private final BooleanGeneratorOption onlyEnabledIfGrammarIsUsed = new BooleanGeneratorOption(false); - - public void setOnlyEnabledIfGrammarIsUsed(final boolean onlyEnabledIfGrammarIsUsed) { - this.onlyEnabledIfGrammarIsUsed.set(onlyEnabledIfGrammarIsUsed); - } - - @Override - public void generate() { - if ((this.onlyEnabledIfGrammarIsUsed.get() && (!this.xbaseUsageDetector.inheritsXtype(this.getLanguage().getGrammar())))) { - return; - } - new GuiceModuleAccess.BindingFactory().addTypeToType(TypeReference.typeRef(IGlobalScopeProvider.class), - TypeReference.typeRef("org.eclipse.xtext.common.types.xtext.TypesAwareDefaultGlobalScopeProvider")).contributeTo(this.getLanguage().getRuntimeGenModule()); - GuiceModuleAccess _runtimeGenModule = this.getLanguage().getRuntimeGenModule(); - _runtimeGenModule.setSuperClass(TypeReference.typeRef("org.eclipse.xtext.common.types.DefaultCommonTypesRuntimeModule")); - new GuiceModuleAccess.BindingFactory().addTypeToType(TypeReference.typeRef("org.eclipse.xtext.ui.editor.contentassist.PrefixMatcher"), - TypeReference.typeRef("org.eclipse.xtext.ui.editor.contentassist.FQNPrefixMatcher")).contributeTo(this.getLanguage().getEclipsePluginGenModule()); - GuiceModuleAccess _eclipsePluginGenModule = this.getLanguage().getEclipsePluginGenModule(); - _eclipsePluginGenModule.setSuperClass(TypeReference.typeRef("org.eclipse.xtext.common.types.ui.DefaultCommonTypesUiModule")); - ManifestAccess _manifest = this.getProjectConfig().getRuntime().getManifest(); - boolean _tripleNotEquals = (_manifest != null); - if (_tripleNotEquals) { - CollectionExtensions.addAll(this.getProjectConfig().getRuntime().getManifest().getRequiredBundles(), - "org.eclipse.xtext.common.types", - "org.objectweb.asm;bundle-version=\"[8.0.1,8.1.0)\";resolution:=optional"); - } - ManifestAccess _manifest_1 = this.getProjectConfig().getRuntimeTest().getManifest(); - boolean _tripleNotEquals_1 = (_manifest_1 != null); - if (_tripleNotEquals_1) { - this.getProjectConfig().getRuntimeTest().getManifest().getRequiredBundles().add( - "org.objectweb.asm;bundle-version=\"[8.0.1,8.1.0)\";resolution:=optional"); - } - ManifestAccess _manifest_2 = this.getProjectConfig().getEclipsePlugin().getManifest(); - boolean _tripleNotEquals_2 = (_manifest_2 != null); - if (_tripleNotEquals_2) { - this.getProjectConfig().getEclipsePlugin().getManifest().getRequiredBundles().add( - "org.eclipse.xtext.common.types.ui"); - } - } - - @Pure - public BooleanGeneratorOption getOnlyEnabledIfGrammarIsUsed() { - return this.onlyEnabledIfGrammarIsUsed; - } -}