/******************************************************************************* * Copyright (c) 2012-2017 Codenvy, S.A. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.plugin.languageserver.ide; import com.google.inject.Inject; import com.google.inject.Singleton; import com.google.web.bindery.event.shared.EventBus; import org.eclipse.che.api.promises.client.Operation; import org.eclipse.che.api.promises.client.OperationException; import org.eclipse.che.ide.api.action.ActionManager; import org.eclipse.che.ide.api.action.DefaultActionGroup; import org.eclipse.che.ide.api.constraints.Anchor; import org.eclipse.che.ide.api.constraints.Constraints; import org.eclipse.che.ide.api.event.FileEvent; import org.eclipse.che.ide.api.extension.Extension; import org.eclipse.che.ide.api.keybinding.KeyBindingAgent; import org.eclipse.che.ide.api.keybinding.KeyBuilder; import org.eclipse.che.ide.dto.DtoFactory; import org.eclipse.che.ide.resource.Path; import org.eclipse.che.ide.util.browser.UserAgent; import org.eclipse.che.ide.util.input.KeyCodeMap; import org.eclipse.che.plugin.languageserver.ide.editor.LanguageServerEditorConfiguration; import org.eclipse.che.plugin.languageserver.ide.editor.quickassist.ApplyTextEditAction; import org.eclipse.che.plugin.languageserver.ide.navigation.declaration.FindDefinitionAction; import org.eclipse.che.plugin.languageserver.ide.navigation.references.FindReferencesAction; import org.eclipse.che.plugin.languageserver.ide.navigation.symbol.GoToSymbolAction; import org.eclipse.che.plugin.languageserver.ide.navigation.workspace.FindSymbolAction; import org.eclipse.che.plugin.languageserver.ide.service.TextDocumentServiceClient; import org.eclipse.lsp4j.DidCloseTextDocumentParams; import org.eclipse.lsp4j.DidOpenTextDocumentParams; import org.eclipse.lsp4j.DidSaveTextDocumentParams; import org.eclipse.lsp4j.TextDocumentIdentifier; import org.eclipse.lsp4j.TextDocumentItem; import static org.eclipse.che.ide.api.action.IdeActions.GROUP_ASSISTANT; @Extension(title = "LanguageServer") @Singleton public class LanguageServerExtension { private final String GROUP_ASSISTANT_REFACTORING = "assistantRefactoringGroup"; @Inject protected void injectCss(LanguageServerResources resources) { // we need to call this method one time resources.css().ensureInjected(); resources.quickOpenListCss().ensureInjected(); } @Inject protected void registerAction(ActionManager actionManager, KeyBindingAgent keyBindingManager, GoToSymbolAction goToSymbolAction, FindSymbolAction findSymbolAction, FindDefinitionAction findDefinitionAction, FindReferencesAction findReferencesAction, ApplyTextEditAction applyTextEditAction) { actionManager.registerAction("LSGoToSymbolAction", goToSymbolAction); actionManager.registerAction("LSFindSymbolAction", findSymbolAction); actionManager.registerAction("LSFindDefinitionAction", findDefinitionAction); actionManager.registerAction("LSFindReferencesAction", findReferencesAction); actionManager.registerAction("lsp.applyTextEdit", applyTextEditAction); DefaultActionGroup assistantGroup = (DefaultActionGroup)actionManager.getAction(GROUP_ASSISTANT); assistantGroup.add(goToSymbolAction, new Constraints(Anchor.BEFORE, GROUP_ASSISTANT_REFACTORING)); assistantGroup.add(findSymbolAction, new Constraints(Anchor.BEFORE, GROUP_ASSISTANT_REFACTORING)); assistantGroup.add(findDefinitionAction, new Constraints(Anchor.BEFORE, GROUP_ASSISTANT_REFACTORING)); assistantGroup.add(findReferencesAction, new Constraints(Anchor.BEFORE, GROUP_ASSISTANT_REFACTORING)); if (UserAgent.isMac()) { keyBindingManager.getGlobal().addKey(new KeyBuilder().control().charCode(KeyCodeMap.F12).build(), "LSGoToSymbolAction"); } else { keyBindingManager.getGlobal().addKey(new KeyBuilder().action().charCode(KeyCodeMap.F12).build(), "LSGoToSymbolAction"); } keyBindingManager.getGlobal().addKey(new KeyBuilder().alt().charCode('n').build(), "LSFindSymbolAction"); keyBindingManager.getGlobal().addKey(new KeyBuilder().alt().charCode(KeyCodeMap.F7).build(), "LSFindReferencesAction"); keyBindingManager.getGlobal().addKey(new KeyBuilder().charCode(KeyCodeMap.F4).build(), "LSFindDefinitionAction"); } @Inject protected void registerFileEventHandler(final EventBus eventBus, final TextDocumentServiceClient serviceClient, final DtoFactory dtoFactory, final LanguageServerFileTypeRegister fileTypeRegister) { eventBus.addHandler(FileEvent.TYPE, new FileEvent.FileEventHandler() { @Override public void onFileOperation(final FileEvent event) { Path location = event.getFile().getLocation(); if (location.getFileExtension() == null || !fileTypeRegister.hasLSForExtension(location.getFileExtension())) { return; } final TextDocumentIdentifier documentId = dtoFactory.createDto(TextDocumentIdentifier.class); documentId.setUri(location.toString()); switch (event.getOperationType()) { case OPEN: onOpen(event, dtoFactory, serviceClient, fileTypeRegister); break; case CLOSE: onClose(documentId, dtoFactory, serviceClient); break; case SAVE: onSave(documentId, dtoFactory, serviceClient); break; } } }); } private void onSave(TextDocumentIdentifier documentId, DtoFactory dtoFactory, TextDocumentServiceClient serviceClient) { DidSaveTextDocumentParams saveEvent = dtoFactory.createDto(DidSaveTextDocumentParams.class); saveEvent.setTextDocument(documentId); serviceClient.didSave(saveEvent); } private void onClose(TextDocumentIdentifier documentId, DtoFactory dtoFactory, TextDocumentServiceClient serviceClient) { DidCloseTextDocumentParams closeEvent = dtoFactory.createDto(DidCloseTextDocumentParams.class); closeEvent.setTextDocument(documentId); serviceClient.didClose(closeEvent); } private void onOpen(final FileEvent event, final DtoFactory dtoFactory, final TextDocumentServiceClient serviceClient, final LanguageServerFileTypeRegister fileTypeRegister) { event.getFile().getContent().then(new Operation<String>() { @Override public void apply(String text) throws OperationException { TextDocumentItem documentItem = dtoFactory.createDto(TextDocumentItem.class); documentItem.setUri(event.getFile().getLocation().toString()); documentItem.setVersion(LanguageServerEditorConfiguration.INITIAL_DOCUMENT_VERSION); documentItem.setText(text); documentItem.setLanguageId(fileTypeRegister.findLangId(event.getFile().getLocation().getFileExtension())); DidOpenTextDocumentParams openEvent = dtoFactory.createDto(DidOpenTextDocumentParams.class); openEvent.setTextDocument(documentItem); openEvent.getTextDocument().setUri(event.getFile().getLocation().toString()); openEvent.setText(text); serviceClient.didOpen(openEvent); } }); } }