CHE-9467. Add ability to get File Type by provider and avoid File Type collision

Signed-off-by: Roman Nikitenko <rnikiten@redhat.com>
6.19.x
Roman Nikitenko 2018-08-17 14:23:08 +03:00 committed by RomanNikitenko
parent ccf7171896
commit 93b0ffed98
18 changed files with 483 additions and 145 deletions

View File

@ -39,6 +39,14 @@ public interface EditorRegistry {
*/
void registerDefaultEditor(@NotNull FileType fileType, @NotNull EditorProvider provider);
/**
* Remove Editor Provider from registry for given file type.
*
* @param fileType the file type
* @param provider the provider to removing
*/
void unRegister(FileType fileType, EditorProvider provider);
/**
* Get editor provide assigned for file type;
*

View File

@ -11,7 +11,13 @@
*/
package org.eclipse.che.ide.api.filetypes;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.util.Collections.EMPTY_SET;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import org.eclipse.che.commons.annotation.Nullable;
import org.vectomatic.dom.svg.ui.SVGResource;
/**
@ -20,7 +26,7 @@ import org.vectomatic.dom.svg.ui.SVGResource;
* <ul>
* <li><code>image</code> - image resource associated with file
* <li><code>extension</code> - extension associated with file
* <li><code>namePattern</code> - name pattern
* <li><code>namePatterns</code> - set of name patterns
* </ul>
*
* @author Evgen Vidolob
@ -28,22 +34,8 @@ import org.vectomatic.dom.svg.ui.SVGResource;
public class FileType {
private SVGResource image;
private String extension;
private String namePattern;
public void setImage(SVGResource image) {
this.image = image;
}
public void setExtension(String extension) {
this.extension = extension;
}
public void setNamePattern(String namePattern) {
this.namePattern = namePattern;
}
private Set<String> namePatterns;
public FileType(SVGResource image, String extension) {
this(image, extension, null);
@ -52,22 +44,68 @@ public class FileType {
public FileType(SVGResource image, String extension, String namePattern) {
this.image = image;
this.extension = extension;
this.namePattern = namePattern;
this.namePatterns = new HashSet<>();
addNamePattern(namePattern);
}
/** @return the extension */
/** Returns the image resource associated with file */
public SVGResource getImage() {
return image;
}
/** Returns the extension associated with file */
public String getExtension() {
return extension;
}
/** @return the namePatterns */
/**
* Returns some element of the name patterns set or {@code null} if the set is empty.
*
* @deprecated FileType can contain a few name patterns, so use {@link #getNamePatterns()} instead
*/
@Nullable
public String getNamePattern() {
return namePattern;
return namePatterns.isEmpty() ? null : namePatterns.iterator().next();
}
/** @return the SVG resource */
public SVGResource getImage() {
return image;
/** Returns the name patterns set describing the file type */
public Set<String> getNamePatterns() {
return namePatterns.isEmpty() ? EMPTY_SET : new HashSet<>(namePatterns);
}
/** Sets image associated with the file type */
public void setImage(SVGResource image) {
this.image = image;
}
/** Sets extension associated with the file type */
public void setExtension(String extension) {
this.extension = extension;
}
/**
* Adds name pattern describing the file type
*
* @deprecated FileType can contain a few name patterns, so use {@link #addNamePattern(String)}
* instead
*/
public void setNamePattern(String namePattern) {
addNamePattern(namePattern);
}
/**
* Adds name pattern describing the file type
*
* @param namePattern pattern for adding
* @return {@code true} if the pattern was added and {@code false} if given pattern is illegal
* ({@code null} or empty) either if it is already present
*/
public boolean addNamePattern(String namePattern) {
if (isNullOrEmpty(namePattern)) {
return false;
}
return namePatterns.add(namePattern);
}
@Override
@ -77,17 +115,15 @@ public class FileType {
FileType fileType = (FileType) o;
if (extension != null ? !extension.equals(fileType.extension) : fileType.extension != null)
if (!Objects.equals(this.extension, fileType.extension)) {
return false;
if (namePattern != null
? !namePattern.equals(fileType.namePattern)
: fileType.namePattern != null) return false;
return true;
} else {
return getNamePatterns().equals(fileType.getNamePatterns());
}
}
@Override
public int hashCode() {
return Objects.hash(extension, namePattern);
return Objects.hash(extension, getNamePatterns());
}
}

View File

@ -12,7 +12,11 @@
package org.eclipse.che.ide.api.filetypes;
import java.util.List;
import java.util.Set;
import javax.validation.constraints.NotNull;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.ide.api.resources.VirtualFile;
import org.vectomatic.dom.svg.ui.SVGResource;
/**
* Registry allows to register new {@link FileType} and get the registered one.
@ -20,10 +24,78 @@ import org.eclipse.che.ide.api.resources.VirtualFile;
* @author Artem Zatsarynnyi
*/
public interface FileTypeRegistry {
/** Provider allows to get registered {@link FileType} and avoid File Type collision. */
interface FileTypeProvider {
/**
* Allows to get {@link FileType} by extension and name pattern.
*
* <p>Returns:
* <li>merged File Type if the File Type Registry contains type which match given {@code
* extension} and {@code namePattern}
* <li>newly created and registered File Type if the File Type Registry does not contain
* corresponding type to merge
*
* @param image associated with the File Type image, optional parameter: default image will be
* used when {@code image} is not provided
* @param extension associated with the File Type extension, mandatory parameter: {@link
* IllegalArgumentException} will be thrown when {@code extension} is not provided
* @param namePattern name pattern describing the File Type, optional parameter
* @throws IllegalArgumentException will be thrown when {@code extension} is not provided
* @return registered File Type
*/
FileType get(
@Nullable SVGResource image, @NotNull String extension, @Nullable String namePattern);
/**
* Allows to get {@link FileType} by extension.
*
* <p>Returns:
* <li>existing File Type if the File Type Registry contains type with such extension
* <li>newly created and registered File Type if the File Type Registry does not contain type
* with such extension
*
* @param image associated with the File Type image, optional parameter: default image will be
* used when {@code image} is not provided
* @param extension associated with the File Type extension, mandatory parameter: {@link
* IllegalArgumentException} will be thrown when {@code extension} is not provided
* @throws IllegalArgumentException will be thrown when {@code extension} is not provided
* @return registered File Type
*/
FileType getByExtension(@Nullable SVGResource image, @NotNull String extension);
/**
* Allows to get the set of {@link FileType}s which match given {@code namePattern}.
*
* <p>Returns:
* <li>set of existing File Types if the File Type Registry contains types which match given
* {@code namePattern}
* <li>newly created and registered by name pattern File Type if the File Type Registry does not
* contain types which match given {@code namePattern}
*
* @param image associated with the File Type image, optional parameter: default image will be
* used when {@code image} is not provided
* @param namePattern name pattern describing the File Type, mandatory parameter: {@link
* IllegalArgumentException} will be thrown when {@code namePattern} is not provided
* @throws IllegalArgumentException will be thrown when {@code namePattern} is not provided
* @return set of registered File Types
*/
Set<FileType> getByNamePattern(@Nullable SVGResource image, @NotNull String namePattern);
}
/** Returns the set of all registered file types. */
Set<FileType> getFileTypes();
/**
* Register the specified file type.
* Registers the specified File Type.
*
* <p>Note: {@link IllegalStateException} will be thrown when given File Type can not be
* registered, so when the collision by file extension is detected. Use {@link FileTypeProvider}
* to register File Type and avoid collision.
*
* @param fileType file type to register
* @throws IllegalArgumentException when given {@code fileType} is {@code null}
* @throws IllegalStateException when given File Type can not be registered
*/
void registerFileType(FileType fileType);
@ -31,6 +103,7 @@ public interface FileTypeRegistry {
* Returns the {@link List} of all registered file types.
*
* @return {@link List} of all registered file types
* @deprecated use {@link #getFileTypes()} instead
*/
List<FileType> getRegisteredFileTypes();

View File

@ -669,7 +669,8 @@ public class EditorAgentImpl
}
final boolean active = file.hasKey("ACTIVE") && file.getBoolean("ACTIVE");
final EditorProvider provider = editorRegistry.findEditorProviderById(providerId);
final FileType fileType = fileTypeRegistry.getFileTypeByFile(resourceFile);
final EditorProvider provider = editorRegistry.getEditor(fileType);
if (provider instanceof AsyncEditorProvider) {
((AsyncEditorProvider) provider)
.createEditor(resourceFile)

View File

@ -59,6 +59,13 @@ public class EditorRegistryImpl implements EditorRegistry {
register(fileType, provider);
}
@Override
public void unRegister(FileType fileType, EditorProvider provider) {
if (fileType != null && registry.containsKey(fileType)) {
registry.get(fileType).remove(provider);
}
}
/** {@inheritDoc} */
@Override
public EditorProvider getEditor(@NotNull FileType fileType) {

View File

@ -0,0 +1,130 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.ide.filetypes;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.util.stream.Collectors.toSet;
import com.google.gwt.regexp.shared.RegExp;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import java.util.Optional;
import java.util.Set;
import javax.validation.constraints.NotNull;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.ide.Resources;
import org.eclipse.che.ide.api.filetypes.FileType;
import org.eclipse.che.ide.api.filetypes.FileTypeRegistry;
import org.eclipse.che.ide.api.filetypes.FileTypeRegistry.FileTypeProvider;
import org.vectomatic.dom.svg.ui.SVGResource;
/**
* Implementation of {@link FileTypeProvider}
*
* @author Roman Nikitenko
*/
@Singleton
public class FileTypeProviderImpl implements FileTypeProvider {
private Resources resources;
private FileTypeRegistry fileTypeRegistry;
private FileType unknownFileType;
@Inject
public FileTypeProviderImpl(
Resources resources,
FileTypeRegistry fileTypeRegistry,
@Named("defaultFileType") FileType unknownFileType) {
this.resources = resources;
this.fileTypeRegistry = fileTypeRegistry;
this.unknownFileType = unknownFileType;
}
public FileType get(
@Nullable SVGResource image, @NotNull String extension, @Nullable String namePattern) {
if (isNullOrEmpty(namePattern)) {
return getByExtension(image, extension);
}
checkArgument(!isNullOrEmpty(extension), "Can not register File Type without extension");
Optional<FileType> fileTypeOptional =
fileTypeRegistry
.getFileTypes()
.stream()
.filter(candidate -> extension.equals(candidate.getExtension()))
.filter(candidate -> canBeMergedByNamePattern(namePattern, candidate))
.findAny();
FileType fileType =
fileTypeOptional.orElseGet(() -> registerNewFileType(image, extension, null));
fileType.addNamePattern(namePattern);
return fileType;
}
public FileType getByExtension(@Nullable SVGResource image, @NotNull String extension) {
checkArgument(!isNullOrEmpty(extension), "Can not register File Type without extension");
FileType duplicate = fileTypeRegistry.getFileTypeByExtension(extension);
if (duplicate != unknownFileType) {
return duplicate;
}
return registerNewFileType(image, extension, null);
}
public Set<FileType> getByNamePattern(@Nullable SVGResource image, @NotNull String namePattern) {
checkArgument(!isNullOrEmpty(namePattern), "Can not register File Type without name pattern");
Set<FileType> result =
fileTypeRegistry
.getFileTypes()
.stream()
.filter(candidate -> canBeMergedByNamePattern(namePattern, candidate))
.peek(candidate -> candidate.addNamePattern(namePattern))
.collect(toSet());
if (result.isEmpty()) {
result.add(registerNewFileType(image, null, namePattern));
}
return result;
}
private FileType registerNewFileType(SVGResource image, String extension, String namePattern) {
FileType newFileType =
new FileType(image == null ? resources.defaultImage() : image, extension, namePattern);
fileTypeRegistry.registerFileType(newFileType);
return newFileType;
}
private boolean canBeMergedByNamePattern(String namePattern, FileType fileTypeCandidate) {
String extensionCandidate = fileTypeCandidate.getExtension();
if (!isNullOrEmpty(extensionCandidate)
&& RegExp.compile(namePattern).test('.' + extensionCandidate)) {
return true;
}
return fileTypeCandidate
.getNamePatterns()
.stream()
.anyMatch(
patternCandidate ->
namePattern.equals(patternCandidate)
|| RegExp.quote(namePattern).equals(patternCandidate));
}
}

View File

@ -11,38 +11,52 @@
*/
package org.eclipse.che.ide.filetypes;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.util.stream.Collectors.toSet;
import static org.eclipse.che.ide.util.NameUtils.getFileExtension;
import com.google.common.base.Strings;
import com.google.gwt.regexp.shared.RegExp;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.eclipse.che.ide.api.filetypes.FileType;
import org.eclipse.che.ide.api.filetypes.FileTypeRegistry;
import org.eclipse.che.ide.api.resources.VirtualFile;
/**
* Implementation of {@link org.eclipse.che.ide.api.filetypes.FileTypeRegistry}
* Implementation of {@link FileTypeRegistry}
*
* @author Artem Zatsarynnyi
*/
@Singleton
public class FileTypeRegistryImpl implements FileTypeRegistry {
private final FileType unknownFileType;
private final List<FileType> fileTypes;
private final Set<FileType> fileTypes = new HashSet<>();
@Inject
public FileTypeRegistryImpl(@Named("defaultFileType") FileType unknownFileType) {
this.unknownFileType = unknownFileType;
fileTypes = new ArrayList<>();
}
@Override
public void registerFileType(FileType fileType) {
fileTypes.add(fileType);
public void registerFileType(FileType candidate) {
if (candidate == null) {
throw new IllegalArgumentException("Can not register Illegal File Type");
}
String extension = candidate.getExtension();
FileType duplicate = getFileTypeByExtension(extension);
if (duplicate != unknownFileType && duplicate != candidate) {
throw new IllegalStateException(
"File Type with extension " + extension + " is already registered");
}
fileTypes.add(candidate);
}
@Override
@ -50,41 +64,88 @@ public class FileTypeRegistryImpl implements FileTypeRegistry {
return new ArrayList<>(fileTypes);
}
@Override
public Set<FileType> getFileTypes() {
return new HashSet<>(fileTypes);
}
@Override
public FileType getFileTypeByFile(VirtualFile file) {
FileType fileType = getFileTypeByFileName(file.getName());
String fileName = file.getName();
String fileExtension = getFileExtension(fileName);
FileType fileType = getFileTypeByFileName(fileName);
if (fileType == unknownFileType) {
fileType = getFileTypeByExtension(getFileExtension(file.getName()));
fileType = getFileTypeByExtension(fileExtension);
}
return fileType != null ? fileType : unknownFileType;
}
@Override
public FileType getFileTypeByExtension(String extension) {
if (!Strings.isNullOrEmpty(extension)) {
for (FileType type : fileTypes) {
if (type.getExtension() != null && type.getExtension().equals(extension)) {
return type;
}
}
if (isNullOrEmpty(extension)) {
return unknownFileType;
}
return unknownFileType;
Set<FileType> typesByExtension =
fileTypes.stream().filter(type -> extension.equals(type.getExtension())).collect(toSet());
if (typesByExtension.isEmpty()) {
return unknownFileType;
}
String nameToTest = '.' + extension;
Optional<FileType> fileType =
typesByExtension
.stream()
.filter(type -> doesFileNameMatchType(nameToTest, type))
.findFirst();
if (fileType.isPresent()) {
return fileType.get();
}
fileType =
typesByExtension.stream().filter(type -> type.getNamePatterns().isEmpty()).findFirst();
return fileType.orElseGet(() -> typesByExtension.iterator().next());
}
@Override
public FileType getFileTypeByFileName(String name) {
if (!Strings.isNullOrEmpty(name)) {
for (FileType type : fileTypes) {
if (type.getNamePattern() != null) {
RegExp regExp = RegExp.compile(type.getNamePattern());
if (regExp.test(name)) {
return type;
}
}
}
if (isNullOrEmpty(name)) {
return unknownFileType;
}
return unknownFileType;
Set<FileType> typesByNamePattern =
fileTypes.stream().filter(type -> doesFileNameMatchType(name, type)).collect(toSet());
if (typesByNamePattern.isEmpty()) {
return unknownFileType;
}
if (typesByNamePattern.size() == 1) {
return typesByNamePattern.iterator().next();
}
String fileExtension = getFileExtension(name);
if (isNullOrEmpty(fileExtension)) {
return typesByNamePattern.iterator().next();
}
Optional<FileType> fileType =
typesByNamePattern
.stream()
.filter(type -> fileExtension.equals(type.getExtension()))
.findFirst();
return fileType.orElseGet(() -> typesByNamePattern.iterator().next());
}
private boolean doesFileNameMatchType(String nameToTest, FileType fileType) {
return fileType
.getNamePatterns()
.stream()
.anyMatch(
namePattern -> {
RegExp regExp = RegExp.compile(namePattern);
return regExp.test(nameToTest);
});
}
}

View File

@ -12,6 +12,8 @@
package org.eclipse.che.plugin.ceylon.ide.inject;
import static com.google.gwt.inject.client.multibindings.GinMultibinder.newSetBinder;
import static org.eclipse.che.plugin.ceylon.ide.CeylonResources.INSTANCE;
import static org.eclipse.che.plugin.ceylon.shared.Constants.CEYLON_EXT;
import com.google.gwt.inject.client.AbstractGinModule;
import com.google.inject.Provides;
@ -20,11 +22,10 @@ import com.google.inject.name.Named;
import org.eclipse.che.api.languageserver.shared.model.LanguageDescription;
import org.eclipse.che.ide.api.extension.ExtensionGinModule;
import org.eclipse.che.ide.api.filetypes.FileType;
import org.eclipse.che.ide.api.filetypes.FileTypeRegistry.FileTypeProvider;
import org.eclipse.che.ide.api.project.type.wizard.ProjectWizardRegistrar;
import org.eclipse.che.plugin.ceylon.ide.CeylonLanguageDescriptionProvider;
import org.eclipse.che.plugin.ceylon.ide.CeylonResources;
import org.eclipse.che.plugin.ceylon.ide.project.CeylonProjectWizardRegistrar;
import org.eclipse.che.plugin.ceylon.shared.Constants;
/** @author David Festal */
@ExtensionGinModule
@ -45,7 +46,7 @@ public class CeylonGinModule extends AbstractGinModule {
@Provides
@Singleton
@Named("CeylonFileType")
protected FileType provideCeylonFile() {
return new FileType(CeylonResources.INSTANCE.ceylonFile(), Constants.CEYLON_EXT);
protected FileType provideCeylonFile(FileTypeProvider fileTypeProvider) {
return fileTypeProvider.getByExtension(INSTANCE.ceylonFile(), CEYLON_EXT);
}
}

View File

@ -12,6 +12,7 @@
package org.eclipse.che.plugin.cpp.ide.inject;
import static com.google.gwt.inject.client.multibindings.GinMultibinder.newSetBinder;
import static org.eclipse.che.plugin.cpp.ide.CppResources.INSTANCE;
import static org.eclipse.che.plugin.cpp.shared.Constants.CPP_EXT;
import static org.eclipse.che.plugin.cpp.shared.Constants.C_EXT;
import static org.eclipse.che.plugin.cpp.shared.Constants.H_EXT;
@ -23,9 +24,9 @@ import com.google.inject.name.Named;
import org.eclipse.che.api.languageserver.shared.model.LanguageDescription;
import org.eclipse.che.ide.api.extension.ExtensionGinModule;
import org.eclipse.che.ide.api.filetypes.FileType;
import org.eclipse.che.ide.api.filetypes.FileTypeRegistry.FileTypeProvider;
import org.eclipse.che.ide.api.project.type.wizard.ProjectWizardRegistrar;
import org.eclipse.che.plugin.cpp.ide.CppLanguageDescriptionProvider;
import org.eclipse.che.plugin.cpp.ide.CppResources;
import org.eclipse.che.plugin.cpp.ide.project.CProjectWizardRegistrar;
import org.eclipse.che.plugin.cpp.ide.project.CppProjectWizardRegistrar;
@ -50,21 +51,21 @@ public class CppGinModule extends AbstractGinModule {
@Provides
@Singleton
@Named("CFileType")
protected FileType provideCFile() {
return new FileType(CppResources.INSTANCE.cFile(), C_EXT);
protected FileType provideCFile(FileTypeProvider fileTypeProvider) {
return fileTypeProvider.getByExtension(INSTANCE.cFile(), C_EXT);
}
@Provides
@Singleton
@Named("CppFileType")
protected FileType provideCppFile() {
return new FileType(CppResources.INSTANCE.cppFile(), CPP_EXT);
protected FileType provideCppFile(FileTypeProvider fileTypeProvider) {
return fileTypeProvider.getByExtension(INSTANCE.cppFile(), CPP_EXT);
}
@Provides
@Singleton
@Named("HFileType")
protected FileType provideHeaderFile() {
return new FileType(CppResources.INSTANCE.cHeaderFile(), H_EXT);
protected FileType provideHeaderFile(FileTypeProvider fileTypeProvider) {
return fileTypeProvider.getByExtension(INSTANCE.cHeaderFile(), H_EXT);
}
}

View File

@ -12,6 +12,8 @@
package org.eclipse.che.plugin.csharp.ide.inject;
import static com.google.gwt.inject.client.multibindings.GinMultibinder.newSetBinder;
import static org.eclipse.che.plugin.csharp.ide.CSharpResources.INSTANCE;
import static org.eclipse.che.plugin.csharp.shared.Constants.CSHARP_EXT;
import com.google.gwt.inject.client.AbstractGinModule;
import com.google.inject.Provides;
@ -20,11 +22,10 @@ import com.google.inject.name.Named;
import org.eclipse.che.api.languageserver.shared.model.LanguageDescription;
import org.eclipse.che.ide.api.extension.ExtensionGinModule;
import org.eclipse.che.ide.api.filetypes.FileType;
import org.eclipse.che.ide.api.filetypes.FileTypeRegistry.FileTypeProvider;
import org.eclipse.che.ide.api.project.type.wizard.ProjectWizardRegistrar;
import org.eclipse.che.plugin.csharp.ide.CSharpLanguageDescriptionProvider;
import org.eclipse.che.plugin.csharp.ide.CSharpResources;
import org.eclipse.che.plugin.csharp.ide.project.CSharpProjectWizardRegistrar;
import org.eclipse.che.plugin.csharp.shared.Constants;
/** @author Vitalii Parfonov */
@ExtensionGinModule
@ -45,7 +46,7 @@ public class CSharpGinModule extends AbstractGinModule {
@Provides
@Singleton
@Named("CSharpFileType")
protected FileType provideCppFile() {
return new FileType(CSharpResources.INSTANCE.csharpFile(), Constants.CSHARP_EXT);
protected FileType provideCSharpFile(FileTypeProvider fileTypeProvider) {
return fileTypeProvider.getByExtension(INSTANCE.csharpFile(), CSHARP_EXT);
}
}

View File

@ -11,6 +11,7 @@
*/
package org.eclipse.che.ide.ext.java.client.inject;
import static org.eclipse.che.ide.ext.java.client.JavaResources.INSTANCE;
import static org.eclipse.che.ide.ext.java.client.action.OrganizeImportsAction.JAVA_ORGANIZE_IMPORT_ID;
import com.google.gwt.inject.client.AbstractGinModule;
@ -23,6 +24,7 @@ import com.google.inject.name.Named;
import org.eclipse.che.ide.api.command.CommandType;
import org.eclipse.che.ide.api.extension.ExtensionGinModule;
import org.eclipse.che.ide.api.filetypes.FileType;
import org.eclipse.che.ide.api.filetypes.FileTypeRegistry.FileTypeProvider;
import org.eclipse.che.ide.api.macro.Macro;
import org.eclipse.che.ide.api.preferences.PreferencePagePresenter;
import org.eclipse.che.ide.api.preferences.PreferencesManager;
@ -30,7 +32,6 @@ import org.eclipse.che.ide.api.reference.FqnProvider;
import org.eclipse.che.ide.api.resources.RenamingSupport;
import org.eclipse.che.ide.api.resources.ResourceInterceptor;
import org.eclipse.che.ide.ext.java.client.CurrentClassFQN_Macro;
import org.eclipse.che.ide.ext.java.client.JavaResources;
import org.eclipse.che.ide.ext.java.client.action.OrganizeImportsAction;
import org.eclipse.che.ide.ext.java.client.action.ProposalAction;
import org.eclipse.che.ide.ext.java.client.command.JavaCommandType;
@ -157,28 +158,28 @@ public class JavaGinModule extends AbstractGinModule {
@Provides
@Singleton
@Named("JavaFileType")
protected FileType provideJavaFile() {
return new FileType(JavaResources.INSTANCE.javaFile(), "java");
protected FileType provideJavaFile(FileTypeProvider fileTypeProvider) {
return fileTypeProvider.getByExtension(INSTANCE.javaFile(), "java");
}
@Provides
@Singleton
@Named("JavaClassFileType")
protected FileType provideJavaClassFile() {
return new FileType(JavaResources.INSTANCE.javaFile(), "class");
protected FileType provideJavaClassFile(FileTypeProvider fileTypeProvider) {
return fileTypeProvider.getByExtension(INSTANCE.javaFile(), "class");
}
@Provides
@Singleton
@Named("JspFileType")
protected FileType provideJspFile() {
return new FileType(JavaResources.INSTANCE.jspFile(), "jsp");
protected FileType provideJspFile(FileTypeProvider fileTypeProvider) {
return fileTypeProvider.getByExtension(INSTANCE.jspFile(), "jsp");
}
@Provides
@Singleton
@Named("JsfFileType")
protected FileType provideJsfFile() {
return new FileType(JavaResources.INSTANCE.jsfFile(), "jsf");
protected FileType provideJsfFile(FileTypeProvider fileTypeProvider) {
return fileTypeProvider.getByExtension(INSTANCE.jsfFile(), "jsf");
}
}

View File

@ -11,12 +11,15 @@
*/
package org.eclipse.che.plugin.languageserver.ide;
import com.google.gwt.regexp.shared.RegExp;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.web.bindery.event.shared.EventBus;
import java.util.Set;
import org.eclipse.che.ide.api.editor.EditorRegistry;
import org.eclipse.che.ide.api.filetypes.FileType;
import org.eclipse.che.ide.api.filetypes.FileTypeRegistry;
import org.eclipse.che.ide.api.filetypes.FileTypeRegistry.FileTypeProvider;
import org.eclipse.che.ide.api.workspace.event.WorkspaceStoppedEvent;
import org.eclipse.che.ide.api.workspace.event.WsAgentServerStoppedEvent;
import org.eclipse.che.plugin.languageserver.ide.editor.LanguageServerEditorProvider;
import org.eclipse.che.plugin.languageserver.ide.registry.LanguageServerRegistry;
import org.eclipse.che.plugin.languageserver.ide.service.LanguageServerServiceClient;
@ -32,22 +35,26 @@ public class LanguageRegexesInitializer {
private final EditorRegistry editorRegistry;
private final LanguageServerEditorProvider editorProvider;
private final LanguageServerServiceClient languageServerServiceClient;
private final FileTypeRegistry fileTypeRegistry;
private final FileTypeProvider fileTypeProvider;
@Inject
public LanguageRegexesInitializer(
EventBus eventBus,
LanguageServerRegistry lsRegistry,
LanguageServerResources resources,
EditorRegistry editorRegistry,
LanguageServerEditorProvider editorProvider,
LanguageServerServiceClient languageServerServiceClient,
FileTypeRegistry fileTypeRegistry) {
FileTypeProvider fileTypeProvider) {
this.lsRegistry = lsRegistry;
this.resources = resources;
this.editorRegistry = editorRegistry;
this.editorProvider = editorProvider;
this.languageServerServiceClient = languageServerServiceClient;
this.fileTypeRegistry = fileTypeRegistry;
this.fileTypeProvider = fileTypeProvider;
eventBus.addHandler(WorkspaceStoppedEvent.TYPE, e -> unInstall());
eventBus.addHandler(WsAgentServerStoppedEvent.TYPE, e -> unInstall());
}
void initialize() {
@ -57,31 +64,14 @@ public class LanguageRegexesInitializer {
languageRegexes -> {
languageRegexes.forEach(
languageRegex -> {
String namePattern = languageRegex.getNamePattern();
FileType fileTypeCandidate = null;
for (FileType fileType : fileTypeRegistry.getRegisteredFileTypes()) {
String extension = fileType.getExtension();
if (extension != null && RegExp.compile(namePattern).test('.' + extension)) {
fileTypeCandidate = fileType;
}
String namePatternCandidate = fileType.getNamePattern();
if ((namePattern.equals(namePatternCandidate)
|| RegExp.quote(namePattern).equals(namePatternCandidate))) {
fileTypeCandidate = fileType;
}
}
if (fileTypeCandidate == null) {
fileTypeCandidate = new FileType(resources.file(), null, namePattern);
fileTypeRegistry.registerFileType(fileTypeCandidate);
} else {
fileTypeCandidate.setNamePattern(namePattern);
}
lsRegistry.registerFileType(fileTypeCandidate, languageRegex);
editorRegistry.registerDefaultEditor(fileTypeCandidate, editorProvider);
Set<FileType> fileTypes =
fileTypeProvider.getByNamePattern(
resources.file(), languageRegex.getNamePattern());
fileTypes.forEach(
fileType -> {
lsRegistry.registerFileType(fileType, languageRegex);
editorRegistry.registerDefaultEditor(fileType, editorProvider);
});
});
})
.catchError(
@ -89,4 +79,14 @@ public class LanguageRegexesInitializer {
LOGGER.error("Error", promiseError.getCause());
});
}
private void unInstall() {
lsRegistry
.getRegisteredFileTypes()
.forEach(
fileType -> {
lsRegistry.unRegister(fileType);
editorRegistry.unRegister(fileType, editorProvider);
});
}
}

View File

@ -14,8 +14,11 @@ package org.eclipse.che.plugin.languageserver.ide.inject;
import com.google.gwt.inject.client.AbstractGinModule;
import com.google.gwt.inject.client.assistedinject.GinFactoryModuleBuilder;
import com.google.gwt.inject.client.multibindings.GinMultibinder;
import com.google.inject.Singleton;
import org.eclipse.che.api.languageserver.shared.model.LanguageDescription;
import org.eclipse.che.ide.api.extension.ExtensionGinModule;
import org.eclipse.che.ide.api.filetypes.FileTypeRegistry.FileTypeProvider;
import org.eclipse.che.ide.filetypes.FileTypeProviderImpl;
import org.eclipse.che.plugin.languageserver.ide.editor.LanguageServerAnnotationModelFactory;
import org.eclipse.che.plugin.languageserver.ide.editor.LanguageServerCodeassistProcessorFactory;
import org.eclipse.che.plugin.languageserver.ide.editor.LanguageServerEditorConfigurationFactory;
@ -48,5 +51,7 @@ public class LanguageServerGinModule extends AbstractGinModule {
bind(ShowMessageJsonRpcReceiver.class).asEagerSingleton();
GinMultibinder.newSetBinder(binder(), LanguageDescription.class);
bind(FileTypeProvider.class).to(FileTypeProviderImpl.class).in(Singleton.class);
}
}

View File

@ -16,7 +16,9 @@ import static org.eclipse.che.ide.api.notification.StatusNotification.Status.FAI
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.che.api.languageserver.shared.model.LanguageRegex;
import org.eclipse.che.api.promises.client.Promise;
@ -91,6 +93,22 @@ public class LanguageServerRegistry {
registeredFileTypes.put(type, description);
}
/**
* Remove given File Type from registry.
*
* @param fileType the file type for removing
*/
public void unRegister(FileType fileType) {
if (fileType != null) {
registeredFileTypes.remove(fileType);
}
}
/** Returns the set of all registered file types. */
public Set<FileType> getRegisteredFileTypes() {
return new HashSet<>(registeredFileTypes.keySet());
}
/**
* Get the language that is registered for this file. May return null if none is found.
*
@ -98,10 +116,7 @@ public class LanguageServerRegistry {
* @return
*/
public LanguageRegex getLanguageFilter(VirtualFile file) {
FileType fileType = fileTypeRegistry.getFileTypeByFile(file);
if (fileType == null) {
return null;
}
FileType fileType = fileTypeRegistry.getFileTypeByFileName(file.getName());
return registeredFileTypes.get(fileType);
}
}

View File

@ -23,10 +23,8 @@ import java.util.List;
import org.eclipse.che.ide.api.action.ActionManager;
import org.eclipse.che.ide.api.action.DefaultActionGroup;
import org.eclipse.che.ide.api.constraints.Constraints;
import org.eclipse.che.ide.api.editor.EditorRegistry;
import org.eclipse.che.ide.api.extension.Extension;
import org.eclipse.che.ide.api.filetypes.FileType;
import org.eclipse.che.ide.api.filetypes.FileTypeRegistry;
import org.eclipse.che.ide.api.filetypes.FileTypeRegistry.FileTypeProvider;
import org.eclipse.che.ide.api.project.type.wizard.PreSelectedProjectTypeManager;
import org.eclipse.che.plugin.maven.client.actions.GetEffectivePomAction;
import org.eclipse.che.plugin.maven.client.actions.ReimportMavenDependenciesAction;
@ -115,11 +113,7 @@ public class MavenExtension {
}
@Inject
private void registerFileType(
FileTypeRegistry fileTypeRegistry,
MavenResources mavenResources,
EditorRegistry editorRegistry) {
FileType pomFile = new FileType(mavenResources.maven(), null, ".*[/\\\\]?pom\\.xml$");
fileTypeRegistry.registerFileType(pomFile);
private void registerFileType(MavenResources mavenResources, FileTypeProvider fileTypeProvider) {
fileTypeProvider.getByNamePattern(mavenResources.maven(), ".*[/\\\\]?pom\\.xml$");
}
}

View File

@ -20,6 +20,7 @@ import com.google.inject.name.Named;
import org.eclipse.che.api.languageserver.shared.model.LanguageDescription;
import org.eclipse.che.ide.api.extension.ExtensionGinModule;
import org.eclipse.che.ide.api.filetypes.FileType;
import org.eclipse.che.ide.api.filetypes.FileTypeRegistry.FileTypeProvider;
import org.eclipse.che.ide.api.project.type.wizard.ProjectWizardRegistrar;
import org.eclipse.che.plugin.php.ide.PhpLanguageDescriptionProvider;
import org.eclipse.che.plugin.php.ide.PhpResources;
@ -45,7 +46,7 @@ public class PhpGinModule extends AbstractGinModule {
@Provides
@Singleton
@Named("PhpFileType")
protected FileType provideCppFile() {
return new FileType(PhpResources.INSTANCE.phpFile(), Constants.PHP_EXT);
protected FileType provideCppFile(FileTypeProvider fileTypeProvider) {
return fileTypeProvider.getByExtension(PhpResources.INSTANCE.phpFile(), Constants.PHP_EXT);
}
}

View File

@ -12,6 +12,7 @@
package org.eclipse.che.plugin.python.ide.inject;
import static com.google.gwt.inject.client.multibindings.GinMultibinder.newSetBinder;
import static org.eclipse.che.plugin.python.ide.PythonResources.INSTANCE;
import static org.eclipse.che.plugin.python.shared.ProjectAttributes.PYTHON_EXT;
import com.google.gwt.inject.client.AbstractGinModule;
@ -21,9 +22,9 @@ import com.google.inject.name.Named;
import org.eclipse.che.api.languageserver.shared.model.LanguageDescription;
import org.eclipse.che.ide.api.extension.ExtensionGinModule;
import org.eclipse.che.ide.api.filetypes.FileType;
import org.eclipse.che.ide.api.filetypes.FileTypeRegistry.FileTypeProvider;
import org.eclipse.che.ide.api.project.type.wizard.ProjectWizardRegistrar;
import org.eclipse.che.plugin.python.ide.PythonLanguageDescriptionProvider;
import org.eclipse.che.plugin.python.ide.PythonResources;
import org.eclipse.che.plugin.python.ide.project.PythonProjectWizardRegistrar;
/** @author Valeriy Svydenko */
@ -44,7 +45,7 @@ public class PythonGinModule extends AbstractGinModule {
@Provides
@Singleton
@Named("PythonFileType")
protected FileType providePythonFile() {
return new FileType(PythonResources.INSTANCE.pythonFile(), PYTHON_EXT);
protected FileType providePythonFile(FileTypeProvider fileTypeProvider) {
return fileTypeProvider.getByExtension(INSTANCE.pythonFile(), PYTHON_EXT);
}
}

View File

@ -20,6 +20,7 @@ import com.google.inject.name.Named;
import org.eclipse.che.api.languageserver.shared.model.LanguageDescription;
import org.eclipse.che.ide.api.extension.ExtensionGinModule;
import org.eclipse.che.ide.api.filetypes.FileType;
import org.eclipse.che.ide.api.filetypes.FileTypeRegistry.FileTypeProvider;
import org.eclipse.che.ide.api.project.type.wizard.ProjectWizardRegistrar;
import org.eclipse.che.plugin.web.client.CamelLanguageDescriptionProvider;
import org.eclipse.che.plugin.web.client.JsonLanguageDescriptionProvider;
@ -56,56 +57,57 @@ public class WebModule extends AbstractGinModule {
@Provides
@Singleton
@Named("CSSFileType")
protected FileType provideCSSFile(WebExtensionResource res) {
return new FileType(res.cssFile(), "css");
protected FileType provideCSSFile(WebExtensionResource res, FileTypeProvider fileTypeProvider) {
return fileTypeProvider.getByExtension(res.cssFile(), "css");
}
@Provides
@Singleton
@Named("LESSFileType")
protected FileType provideLESSFile(WebExtensionResource res) {
return new FileType(res.lessFile(), "less");
protected FileType provideLESSFile(WebExtensionResource res, FileTypeProvider fileTypeProvider) {
return fileTypeProvider.getByExtension(res.lessFile(), "less");
}
@Provides
@Singleton
@Named("JSFileType")
protected FileType provideJSFile(WebExtensionResource res) {
return new FileType(res.jsFile(), "js");
protected FileType provideJSFile(WebExtensionResource res, FileTypeProvider fileTypeProvider) {
return fileTypeProvider.getByExtension(res.jsFile(), "js");
}
@Provides
@Singleton
@Named("ES6FileType")
protected FileType provideES6File(WebExtensionResource res) {
return new FileType(res.jsFile(), "es6");
protected FileType provideES6File(WebExtensionResource res, FileTypeProvider fileTypeProvider) {
return fileTypeProvider.getByExtension(res.jsFile(), "es6");
}
@Provides
@Singleton
@Named("JSXFileType")
protected FileType provideJSXFile(WebExtensionResource res) {
return new FileType(res.jsFile(), "jsx");
protected FileType provideJSXFile(WebExtensionResource res, FileTypeProvider fileTypeProvider) {
return fileTypeProvider.getByExtension(res.jsFile(), "jsx");
}
@Provides
@Singleton
@Named("TypeScript")
protected FileType provideTypeScriptFile(WebExtensionResource res) {
return new FileType(res.jsFile(), "ts");
protected FileType provideTypeScriptFile(
WebExtensionResource res, FileTypeProvider fileTypeProvider) {
return fileTypeProvider.getByExtension(res.jsFile(), "ts");
}
@Provides
@Singleton
@Named("HTMLFileType")
protected FileType provideHTMLFile(WebExtensionResource res) {
return new FileType(res.htmlFile(), "html");
protected FileType provideHTMLFile(WebExtensionResource res, FileTypeProvider fileTypeProvider) {
return fileTypeProvider.getByExtension(res.htmlFile(), "html");
}
@Provides
@Singleton
@Named("PHPFileType")
protected FileType providePHPFile(WebExtensionResource res) {
return new FileType(res.phpFile(), "php");
protected FileType providePHPFile(WebExtensionResource res, FileTypeProvider fileTypeProvider) {
return fileTypeProvider.getByExtension(res.phpFile(), "php");
}
}