summaryrefslogtreecommitdiff
path: root/plugins/properties
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/properties')
-rw-r--r--plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties3
-rw-r--r--plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesUtil.java75
-rw-r--r--plugins/properties/properties-psi-api/src/com/intellij/lang/properties/ResourceBundle.java20
-rw-r--r--plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/BundleNameEvaluator.java2
-rw-r--r--plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/CustomResourceBundle.java109
-rw-r--r--plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/CustomResourceBundleState.java93
-rw-r--r--plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java30
-rw-r--r--plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java20
-rw-r--r--plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java256
-rw-r--r--plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManagerState.java72
-rw-r--r--plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundlePropertyStructureViewElement.java11
-rw-r--r--plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertiesFileImpl.java3
-rw-r--r--plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java4
-rw-r--r--plugins/properties/properties-psi-impl/src/com/intellij/properties/PropertiesCoreEnvironment.java2
-rw-r--r--plugins/properties/src/META-INF/plugin.xml7
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/PropertiesFilesManager.java9
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/ResourceBundleReference.java4
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/customizeActions/CombinePropertiesFilesAction.java155
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/customizeActions/DissociateResourceBundleAction.java80
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java32
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java4
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditorProvider.java2
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleStructureViewComponent.java2
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleUtil.java2
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/projectView/CustomResourceBundlePropertiesFileNode.java56
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleGrouper.java5
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleNode.java2
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/refactoring/rename/RenamePropertyProcessor.java2
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/refactoring/rename/ResourceBundleRenamer.java9
-rw-r--r--plugins/properties/testSrc/com/intellij/lang/properties/CustomResourceBundleTest.java139
-rw-r--r--plugins/properties/testSrc/com/intellij/lang/properties/PropertiesUtilTest.java17
31 files changed, 1092 insertions, 135 deletions
diff --git a/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties b/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties
index 61b69161c5e3..f8439f059b7e 100644
--- a/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties
+++ b/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties
@@ -52,5 +52,8 @@ resource.bundle.renamer.dialog.description=Rename resource bundle properties fil
resource.bundle.renamer.entity.name=Resource bundle
resource.bundle.renamer.option=Rename bound &resource bundle
+combine.properties.files.prompt.text=Combine properties files to resource bundle with bundle base name
+combine.properties.files.title=Combine to Resource Bundle
+
inline.property.refactoring=Inline Property
inline.property.confirmation=Inline property ''{0}'' with value ''{1}''?
diff --git a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesUtil.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesUtil.java
index bb9b9449166f..0867b6b5faa1 100644
--- a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesUtil.java
+++ b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesUtil.java
@@ -16,16 +16,14 @@
package com.intellij.lang.properties;
import com.intellij.lang.properties.psi.PropertiesFile;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
-import com.intellij.openapi.util.NullableComputable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
-import com.intellij.psi.PsiFile;
import com.intellij.util.SmartList;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -38,8 +36,8 @@ import java.util.regex.Pattern;
* @author cdr
*/
public class PropertiesUtil {
- private final static Pattern LOCALE_PATTERN = Pattern.compile("(_[a-zA-Z]{2,8}(_[a-zA-Z]{2}|[0-9]{3})?(_[\\w\\-]+)?)\\.[^_]+$");
- private final static Locale DEFAULT_LOCALE = new Locale("", "", "");
+ public final static Pattern LOCALE_PATTERN = Pattern.compile("(_[a-zA-Z]{2,8}(_[a-zA-Z]{2}|[0-9]{3})?(_[\\w\\-]+)?)\\.[^_]+$");
+ public static final Set<Character> BASE_NAME_BORDER_CHAR = ContainerUtil.newHashSet('-', '_', '.');
/**
@@ -59,12 +57,28 @@ public class PropertiesUtil {
}
@NotNull
- public static String getBaseName(@NotNull PsiFile file) {
- return getBaseName(file.getContainingFile().getVirtualFile());
+ public static String getDefaultBaseName(final Collection<PropertiesFile> files) {
+ String commonPrefix = null;
+ for (PropertiesFile file : files) {
+ final String baseName = file.getVirtualFile().getNameWithoutExtension();
+ if (commonPrefix == null) {
+ commonPrefix = baseName;
+ } else {
+ commonPrefix = StringUtil.commonPrefix(commonPrefix, baseName);
+ if (commonPrefix.isEmpty()) {
+ break;
+ }
+ }
+ }
+ assert commonPrefix != null;
+ if (!commonPrefix.isEmpty() && BASE_NAME_BORDER_CHAR.contains(commonPrefix.charAt(commonPrefix.length() - 1))) {
+ commonPrefix = commonPrefix.substring(0, commonPrefix.length() - 1);
+ }
+ return commonPrefix;
}
@NotNull
- public static String getBaseName(@NotNull VirtualFile file) {
+ public static String getDefaultBaseName(@NotNull final VirtualFile file) {
final String name = file.getName();
final Matcher matcher = LOCALE_PATTERN.matcher(name);
final String baseNameWithExtension;
@@ -105,44 +119,21 @@ public class PropertiesUtil {
return null;
}
- @Nullable
- public static String getFullName(final PropertiesFile propertiesFile) {
- return ApplicationManager.getApplication().runReadAction(new NullableComputable<String>() {
- public String compute() {
- PsiDirectory directory = propertiesFile.getParent();
- String packageQualifiedName = getPackageQualifiedName(directory);
- if (packageQualifiedName == null) {
- return null;
- }
- StringBuilder qName = new StringBuilder(packageQualifiedName);
- if (qName.length() > 0) {
- qName.append(".");
- }
- qName.append(getBaseName(propertiesFile.getContainingFile()));
- return qName.toString();
- }
- });
- }
-
+ /**
+ * @deprecated use PropertiesUtil.findAllProperties(ResourceBundle resourceBundle, String key)
+ */
@NotNull
- public static Locale getLocale(final VirtualFile propertiesFile) {
- String name = propertiesFile.getName();
- final Matcher matcher = LOCALE_PATTERN.matcher(name);
- if (matcher.find()) {
- String rawLocale = matcher.group(1);
- String[] splittedRawLocale = rawLocale.split("_");
- if (splittedRawLocale.length > 1 && splittedRawLocale[1].length() == 2) {
- final String language = splittedRawLocale[1];
- final String country = splittedRawLocale.length > 2 ? splittedRawLocale[2] : "";
- final String variant = splittedRawLocale.length > 3 ? splittedRawLocale[3] : "";
- return new Locale(language, country, variant);
- }
+ @Deprecated
+ public static List<IProperty> findAllProperties(Project project, @NotNull ResourceBundle resourceBundle, String key) {
+ List<IProperty> result = new SmartList<IProperty>();
+ List<PropertiesFile> propertiesFiles = resourceBundle.getPropertiesFiles();
+ for (PropertiesFile propertiesFile : propertiesFiles) {
+ result.addAll(propertiesFile.findPropertiesByKey(key));
}
- return DEFAULT_LOCALE;
+ return result;
}
- @NotNull
- public static List<IProperty> findAllProperties(Project project, @NotNull ResourceBundle resourceBundle, String key) {
+ public static List<IProperty> findAllProperties(@NotNull ResourceBundle resourceBundle, String key) {
List<IProperty> result = new SmartList<IProperty>();
List<PropertiesFile> propertiesFiles = resourceBundle.getPropertiesFiles();
for (PropertiesFile propertiesFile : propertiesFiles) {
diff --git a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/ResourceBundle.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/ResourceBundle.java
index 7ea56269949d..b53cdae358f0 100644
--- a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/ResourceBundle.java
+++ b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/ResourceBundle.java
@@ -26,8 +26,8 @@ import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiDirectory;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.List;
@@ -38,26 +38,34 @@ public abstract class ResourceBundle {
public abstract List<PropertiesFile> getPropertiesFiles();
/**
- * @deprecated, use getPropertiesFiles() instead this method
+ * @deprecated use getPropertiesFiles() instead this method
*/
@Deprecated
@NotNull
- public abstract List<PropertiesFile> getPropertiesFiles(final Project project);
+ public List<PropertiesFile> getPropertiesFiles(final Project project) {
+ return getPropertiesFiles();
+ }
@NotNull
public abstract PropertiesFile getDefaultPropertiesFile();
/**
- * @deprecated, use getDefaultPropertiesFile() instead this method
+ * @deprecated use getDefaultPropertiesFile() instead this method
*/
@Deprecated
@NotNull
- public abstract PropertiesFile getDefaultPropertiesFile(final Project project);
+ public PropertiesFile getDefaultPropertiesFile(final Project project) {
+ return getDefaultPropertiesFile();
+ }
@NotNull
public abstract String getBaseName();
- @NotNull
+ /**
+ * @return null if resource bundle is not default ( == instance of ResourceBundleImpl)
+ */
+ @Deprecated
+ @Nullable
public abstract VirtualFile getBaseDirectory();
@NotNull
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/BundleNameEvaluator.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/BundleNameEvaluator.java
index ebe28b38b37e..52b57238d138 100644
--- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/BundleNameEvaluator.java
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/BundleNameEvaluator.java
@@ -37,7 +37,7 @@ public interface BundleNameEvaluator {
if (qName.length() > 0) {
qName.append(".");
}
- qName.append(PropertiesUtil.getBaseName(psiFile));
+ qName.append(ResourceBundleManager.getInstance(psiFile.getProject()).getBaseName(psiFile));
return qName.toString();
}
return null;
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/CustomResourceBundle.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/CustomResourceBundle.java
new file mode 100644
index 000000000000..d712dc3d8655
--- /dev/null
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/CustomResourceBundle.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.properties;
+
+import com.intellij.lang.properties.psi.PropertiesFile;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.psi.PsiManager;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class CustomResourceBundle extends ResourceBundle {
+ private final static Logger LOG = Logger.getInstance(CustomResourceBundle.class);
+
+ private final List<PropertiesFile> myFiles;
+ private final String myBaseName;
+
+ private CustomResourceBundle(final List<PropertiesFile> files, final @NotNull String baseName) {
+ LOG.assertTrue(!files.isEmpty());
+ myFiles = new ArrayList<PropertiesFile>(files);
+ Collections.sort(myFiles, new Comparator<PropertiesFile>() {
+ @Override
+ public int compare(PropertiesFile f1, PropertiesFile f2) {
+ return f1.getName().compareTo(f2.getName());
+ }
+ });
+ myBaseName = baseName;
+ }
+
+ public static CustomResourceBundle fromState(final CustomResourceBundleState state, final Project project) {
+ final PsiManager psiManager = PsiManager.getInstance(project);
+ final List<PropertiesFile> files =
+ ContainerUtil.map(state.getFiles(VirtualFileManager.getInstance()), new Function<VirtualFile, PropertiesFile>() {
+ @Override
+ public PropertiesFile fun(VirtualFile virtualFile) {
+ return PropertiesImplUtil.getPropertiesFile(psiManager.findFile(virtualFile));
+ }
+ });
+ return files.size() < 2 ? null : new CustomResourceBundle(files, state.getBaseName());
+ }
+
+ @NotNull
+ @Override
+ public List<PropertiesFile> getPropertiesFiles() {
+ return myFiles;
+ }
+
+ @NotNull
+ @Override
+ public PropertiesFile getDefaultPropertiesFile() {
+ return ContainerUtil.getFirstItem(myFiles);
+ }
+
+ @NotNull
+ @Override
+ public String getBaseName() {
+ return myBaseName;
+ }
+
+ @Nullable
+ @Override
+ public VirtualFile getBaseDirectory() {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public Project getProject() {
+ return getDefaultPropertiesFile().getProject();
+ }
+
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final CustomResourceBundle resourceBundle = (CustomResourceBundle)o;
+ return resourceBundle.getPropertiesFiles().equals(resourceBundle.getPropertiesFiles()) &&
+ resourceBundle.getBaseName().equals(getBaseName());
+ }
+
+ public int hashCode() {
+ return myFiles.hashCode() * 31 + myBaseName.hashCode();
+ }
+}
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/CustomResourceBundleState.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/CustomResourceBundleState.java
new file mode 100644
index 000000000000..9be149d6a4db
--- /dev/null
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/CustomResourceBundleState.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.properties;
+
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.HashSet;
+import com.intellij.util.xmlb.annotations.AbstractCollection;
+import com.intellij.util.xmlb.annotations.Property;
+import com.intellij.util.xmlb.annotations.Tag;
+import com.intellij.util.xmlb.annotations.Transient;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Dmitry Batkovich
+ */
+@Tag("custom-resource-bundle")
+public class CustomResourceBundleState {
+
+ @Property(surroundWithTag = false)
+ @AbstractCollection(surroundWithTag = false, elementTag = "file", elementValueAttribute = "value")
+ public Set<String> myFileUrls = new HashSet<String>();
+
+ @Tag("base-name")
+ public String myBaseName;
+
+ @Transient
+ @NotNull
+ public String getBaseName() {
+ return myBaseName;
+ }
+
+ public Set<String> getFileUrls() {
+ return myFileUrls;
+ }
+
+ public List<VirtualFile> getFiles(@NotNull final VirtualFileManager manager) {
+ return ContainerUtil.mapNotNull(getFileUrls(), new Function<String, VirtualFile>() {
+ @Override
+ public VirtualFile fun(String url) {
+ return manager.findFileByUrl(url);
+ }
+ });
+ }
+
+ @Nullable
+ public CustomResourceBundleState removeNonExistentFiles(final VirtualFileManager virtualFileManager) {
+ final List<String> existentFiles = ContainerUtil.filter(myFileUrls, new Condition<String>() {
+ @Override
+ public boolean value(String url) {
+ return virtualFileManager.findFileByUrl(url) != null;
+ }
+ });
+ if (existentFiles.isEmpty()) {
+ return null;
+ }
+ final CustomResourceBundleState customResourceBundleState = new CustomResourceBundleState();
+ customResourceBundleState.myFileUrls.addAll(existentFiles);
+ customResourceBundleState.myBaseName = myBaseName;
+ return customResourceBundleState;
+ }
+
+ public CustomResourceBundleState addAll(final Collection<String> urls) {
+ myFileUrls.addAll(urls);
+ return this;
+ }
+
+ public CustomResourceBundleState setBaseName(String baseName) {
+ myBaseName = baseName;
+ return this;
+ }
+}
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java
index f667b1a93da0..15e73791f8ea 100644
--- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java
@@ -15,6 +15,7 @@
*/
package com.intellij.lang.properties;
+import com.intellij.lang.HtmlScriptContentProvider;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.lang.properties.psi.PropertyKeyIndex;
import com.intellij.lang.properties.xml.XmlPropertiesFileImpl;
@@ -48,7 +49,23 @@ public class PropertiesImplUtil extends PropertiesUtil {
if (!containingFile.isValid()) {
return EmptyResourceBundle.getInstance();
}
- final String baseName = getBaseName(containingFile);
+ final ResourceBundleManager manager = ResourceBundleManager.getInstance(representative.getProject());
+ final CustomResourceBundle customResourceBundle =
+ manager.getCustomResourceBundle(representative);
+ if (customResourceBundle != null) {
+ return customResourceBundle;
+ }
+
+ final VirtualFile virtualFile = representative.getVirtualFile();
+ if (virtualFile == null) {
+ return EmptyResourceBundle.getInstance();
+ }
+ if (manager.isDefaultDissociated(virtualFile)) {
+ return new ResourceBundleImpl(representative);
+ }
+
+
+ final String baseName = manager.getBaseName(containingFile);
final PsiDirectory directory = ApplicationManager.getApplication().runReadAction(new Computable<PsiDirectory>() {
@Nullable
public PsiDirectory compute() {
@@ -61,14 +78,9 @@ public class PropertiesImplUtil extends PropertiesUtil {
@Nullable
private static ResourceBundle getResourceBundle(@NotNull final String baseName, @NotNull final PsiDirectory baseDirectory) {
PropertiesFile defaultPropertiesFile = null;
- final PsiFile[] files = ApplicationManager.getApplication().runReadAction(new Computable<PsiFile[]>() {
- @Override
- public PsiFile[] compute() {
- return baseDirectory.getFiles();
- }
- });
- for (final PsiFile psiFile : files) {
- if (baseName.equals(getBaseName(psiFile))) {
+ final ResourceBundleManager bundleBaseNameManager = ResourceBundleManager.getInstance(baseDirectory.getProject());
+ for (final PsiFile psiFile : baseDirectory.getFiles()) {
+ if (baseName.equals(bundleBaseNameManager.getBaseName(psiFile))) {
final PropertiesFile propertiesFile = getPropertiesFile(psiFile);
if (propertiesFile != null) {
if (defaultPropertiesFile == null || defaultPropertiesFile.getName().compareTo(propertiesFile.getName()) > 0) {
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java
index ca5c8aa39a36..bad9957f7523 100644
--- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java
@@ -27,6 +27,7 @@ import com.intellij.psi.PsiFile;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;
+import java.util.Collections;
import java.util.List;
public class ResourceBundleImpl extends ResourceBundle {
@@ -39,12 +40,15 @@ public class ResourceBundleImpl extends ResourceBundle {
@NotNull
@Override
public List<PropertiesFile> getPropertiesFiles() {
+ if (ResourceBundleManager.getInstance(getProject()).isDefaultDissociated(myDefaultPropertiesFile.getVirtualFile())) {
+ return Collections.singletonList(myDefaultPropertiesFile);
+ }
PsiFile[] children = myDefaultPropertiesFile.getParent().getFiles();
final String baseName = getBaseName();
List<PropertiesFile> result = new SmartList<PropertiesFile>();
for (PsiFile file : children) {
if (!file.isValid() || file.getVirtualFile().getExtension() == null) continue;
- if (Comparing.strEqual(PropertiesUtil.getBaseName(file), baseName)) {
+ if (Comparing.strEqual(PropertiesUtil.getDefaultBaseName(file.getVirtualFile()), baseName)) {
PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(file);
if (propertiesFile != null) {
result.add(propertiesFile);
@@ -56,26 +60,14 @@ public class ResourceBundleImpl extends ResourceBundle {
@NotNull
@Override
- public List<PropertiesFile> getPropertiesFiles(final Project project) {
- return getPropertiesFiles();
- }
-
- @NotNull
- @Override
public PropertiesFile getDefaultPropertiesFile() {
return myDefaultPropertiesFile;
}
@NotNull
@Override
- public PropertiesFile getDefaultPropertiesFile(final Project project) {
- return getDefaultPropertiesFile();
- }
-
- @NotNull
- @Override
public String getBaseName() {
- return PropertiesUtil.getBaseName(myDefaultPropertiesFile.getContainingFile());
+ return ResourceBundleManager.getInstance(getProject()).getBaseName(myDefaultPropertiesFile.getContainingFile());
}
@NotNull
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java
new file mode 100644
index 000000000000..a01c123f8763
--- /dev/null
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.properties;
+
+import com.intellij.lang.properties.psi.PropertiesFile;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.components.*;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.NullableComputable;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.*;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.Locale;
+import java.util.regex.Matcher;
+
+/**
+ * @author Dmitry Batkovich
+ */
+@State(
+ name = "ResourceBundleManager",
+ storages = {
+ @Storage(file = StoragePathMacros.PROJECT_FILE),
+ @Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/resourceBundles.xml", scheme = StorageScheme.DIRECTORY_BASED)
+ })
+public class ResourceBundleManager implements PersistentStateComponent<ResourceBundleManagerState> {
+ private final static Logger LOG = Logger.getInstance(ResourceBundleManager.class);
+ private final static Locale DEFAULT_LOCALE = new Locale("", "", "");
+
+ private ResourceBundleManagerState myState = new ResourceBundleManagerState();
+
+ public ResourceBundleManager(final PsiManager manager) {
+ manager.addPsiTreeChangeListener(new PsiTreeChangeAdapter() {
+ @Override
+ public void childMoved(@NotNull PsiTreeChangeEvent event) {
+ final PsiElement child = event.getChild();
+ if (!(child instanceof PsiFile)) {
+ return;
+ }
+ final PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile((PsiFile)child);
+ if (propertiesFile == null) {
+ return;
+ }
+ final String oldParentUrl = getUrl(event.getOldParent());
+ final String newParentUrl = getUrl(event.getNewParent());
+ if (oldParentUrl == null || newParentUrl == null) {
+ return;
+ }
+ final String newUrl = propertiesFile.getVirtualFile().getUrl();
+ final String oldUrl = oldParentUrl + newUrl.substring(newParentUrl.length());
+ if (myState.getDissociatedFiles().remove(oldUrl)) {
+ myState.getDissociatedFiles().add(newUrl);
+ }
+
+ for (CustomResourceBundleState customResourceBundleState : myState.getCustomResourceBundles()) {
+ if (customResourceBundleState.getFileUrls().remove(oldUrl)) {
+ customResourceBundleState.getFileUrls().add(newUrl);
+ break;
+ }
+ }
+ }
+
+ @Nullable
+ private String getUrl(PsiElement element) {
+ return !(element instanceof PsiDirectory) ? null : ((PsiDirectory)element).getVirtualFile().getUrl();
+ }
+
+ @Override
+ public void childReplaced(@NotNull PsiTreeChangeEvent event) {
+ super.childReplaced(event);
+ }
+
+ @Override
+ public void beforeChildMovement(@NotNull PsiTreeChangeEvent event) {
+ super.beforeChildMovement(event);
+ }
+
+ @Override
+ public void propertyChanged(@NotNull PsiTreeChangeEvent event) {
+ super.propertyChanged(event);
+ }
+
+ @Override
+ public void childRemoved(@NotNull PsiTreeChangeEvent event) {
+ final PsiElement child = event.getChild();
+ if (!(child instanceof PsiFile)) {
+ return;
+ }
+ PropertiesFile file = PropertiesImplUtil.getPropertiesFile((PsiFile)child);
+ if (file == null) {
+ return;
+ }
+ final VirtualFile virtualFile = file.getVirtualFile();
+ final String url = virtualFile.getUrl();
+ myState.getDissociatedFiles().remove(url);
+ for (CustomResourceBundleState customResourceBundleState : myState.getCustomResourceBundles()) {
+ if (customResourceBundleState.getFileUrls().remove(url)) {
+ if (customResourceBundleState.getFileUrls().size() < 2) {
+ myState.getCustomResourceBundles().remove(customResourceBundleState);
+ }
+ break;
+ }
+ }
+ }
+ });
+ }
+
+ public static ResourceBundleManager getInstance(final Project project) {
+ return ServiceManager.getService(project, ResourceBundleManager.class);
+ }
+
+ @Nullable
+ public String getFullName(final @NotNull PropertiesFile propertiesFile) {
+ return ApplicationManager.getApplication().runReadAction(new NullableComputable<String>() {
+ public String compute() {
+ final PsiDirectory directory = propertiesFile.getParent();
+ final String packageQualifiedName = PropertiesUtil.getPackageQualifiedName(directory);
+ if (packageQualifiedName == null) {
+ return null;
+ }
+ final StringBuilder qName = new StringBuilder(packageQualifiedName);
+ if (qName.length() > 0) {
+ qName.append(".");
+ }
+ qName.append(getBaseName(propertiesFile.getContainingFile()));
+ return qName.toString();
+ }
+ });
+ }
+
+ @NotNull
+ public Locale getLocale(final @NotNull VirtualFile propertiesFile) {
+ final String customResourceBundleName = getCustomResourceBundleName(propertiesFile);
+
+ String name = propertiesFile.getName();
+ if (customResourceBundleName != null) {
+ name = name.substring(customResourceBundleName.length());
+ }
+
+ final Matcher matcher = PropertiesUtil.LOCALE_PATTERN.matcher(name);
+ if (matcher.find()) {
+ final String rawLocale = matcher.group(1);
+ final String[] splittedRawLocale = rawLocale.split("_");
+ if (splittedRawLocale.length > 1 && splittedRawLocale[1].length() >= 2) {
+ final String language = splittedRawLocale[1];
+ final String country = splittedRawLocale.length > 2 ? splittedRawLocale[2] : "";
+ final String variant = splittedRawLocale.length > 3 ? splittedRawLocale[3] : "";
+ return new Locale(language, country, variant);
+ }
+ }
+ return DEFAULT_LOCALE;
+ }
+
+ @NotNull
+ public String getBaseName(@NotNull final PsiFile file) {
+ return getBaseName(file.getVirtualFile());
+ }
+
+ @NotNull
+ private String getBaseName(@NotNull final VirtualFile file) {
+ final CustomResourceBundleState customResourceBundle = getCustomResourceBundleState(file);
+ if (customResourceBundle != null) {
+ return customResourceBundle.getBaseName();
+ }
+ if (isDefaultDissociated(file)) {
+ return file.getNameWithoutExtension();
+ }
+ return PropertiesUtil.getDefaultBaseName(file);
+ }
+
+
+ public void dissociateResourceBundle(final @NotNull ResourceBundle resourceBundle) {
+ if (resourceBundle instanceof CustomResourceBundle) {
+ final CustomResourceBundleState state =
+ getCustomResourceBundleState(resourceBundle.getDefaultPropertiesFile().getVirtualFile());
+ LOG.assertTrue(state != null);
+ myState.getCustomResourceBundles().remove(state);
+ } else {
+ for (final PropertiesFile propertiesFile : resourceBundle.getPropertiesFiles()) {
+ final VirtualFile file = propertiesFile.getContainingFile().getVirtualFile();
+ myState.getDissociatedFiles().add(file.getUrl());
+ }
+ }
+ }
+
+ public void combineToResourceBundle(final @NotNull List<PropertiesFile> propertiesFiles, final String baseName) {
+ myState.getCustomResourceBundles()
+ .add(new CustomResourceBundleState().addAll(ContainerUtil.map(propertiesFiles, new Function<PropertiesFile, String>() {
+ @Override
+ public String fun(PropertiesFile file) {
+ return file.getVirtualFile().getUrl();
+ }
+ })).setBaseName(baseName));
+ }
+
+ @Nullable
+ public CustomResourceBundle getCustomResourceBundle(final @NotNull PropertiesFile file) {
+ final VirtualFile virtualFile = file.getVirtualFile();
+ if (virtualFile == null) {
+ return null;
+ }
+ final CustomResourceBundleState state = getCustomResourceBundleState(virtualFile);
+ return state == null ? null : CustomResourceBundle.fromState(state, file.getProject());
+ }
+
+ public boolean isDefaultDissociated(final @NotNull VirtualFile virtualFile) {
+ final String url = virtualFile.getUrl();
+ return myState.getDissociatedFiles().contains(url) || getCustomResourceBundleState(virtualFile) != null;
+ }
+
+ @Nullable
+ private String getCustomResourceBundleName(final @NotNull VirtualFile virtualFile) {
+ final CustomResourceBundleState customResourceBundle = getCustomResourceBundleState(virtualFile);
+ return customResourceBundle == null ? null : customResourceBundle.getBaseName();
+ }
+
+ @Nullable
+ private CustomResourceBundleState getCustomResourceBundleState(final @NotNull VirtualFile virtualFile) {
+ final String url = virtualFile.getUrl();
+ for (CustomResourceBundleState customResourceBundleState : myState.getCustomResourceBundles()) {
+ if (customResourceBundleState.getFileUrls().contains(url)) {
+ return customResourceBundleState;
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public ResourceBundleManagerState getState() {
+ return myState.isEmpty() ? null : myState;
+ }
+
+ @Override
+ public void loadState(ResourceBundleManagerState state) {
+ myState = state.removeNonExistentFiles();
+ }
+}
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManagerState.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManagerState.java
new file mode 100644
index 000000000000..c4d1e5c5cb2d
--- /dev/null
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManagerState.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.properties;
+
+import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.util.containers.HashSet;
+import com.intellij.util.xmlb.annotations.AbstractCollection;
+import com.intellij.util.xmlb.annotations.Property;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ResourceBundleManagerState {
+
+ @Property(surroundWithTag = false)
+ @AbstractCollection(elementValueAttribute = "url", elementTag = "file", surroundWithTag = false)
+ public Set<String> myDissociatedFiles = new HashSet<String>();
+
+ @Property(surroundWithTag = false)
+ @AbstractCollection(elementTag = "custom-rb", surroundWithTag = false)
+ public List<CustomResourceBundleState> myCustomResourceBundles = new ArrayList<CustomResourceBundleState>();
+
+ public Set<String> getDissociatedFiles() {
+ return myDissociatedFiles;
+ }
+
+ public List<CustomResourceBundleState> getCustomResourceBundles() {
+ return myCustomResourceBundles;
+ }
+
+ public boolean isEmpty() {
+ return myCustomResourceBundles.isEmpty() && myDissociatedFiles.isEmpty();
+ }
+
+ public ResourceBundleManagerState removeNonExistentFiles() {
+ final ResourceBundleManagerState newState = new ResourceBundleManagerState();
+
+ final VirtualFileManager virtualFileManager = VirtualFileManager.getInstance();
+
+ for (final String dissociatedFileUrl : myDissociatedFiles) {
+ if (virtualFileManager.findFileByUrl(dissociatedFileUrl) != null) {
+ newState.myDissociatedFiles.add(dissociatedFileUrl);
+ }
+ }
+
+ for (CustomResourceBundleState customResourceBundle : myCustomResourceBundles) {
+ final CustomResourceBundleState updatedCustomResourceBundle = customResourceBundle.removeNonExistentFiles(virtualFileManager);
+ if (updatedCustomResourceBundle != null) {
+ newState.myCustomResourceBundles.add(updatedCustomResourceBundle);
+ }
+ }
+
+ return newState;
+ }
+}
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundlePropertyStructureViewElement.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundlePropertyStructureViewElement.java
index 724a794ca3bb..14cb1cb940c4 100644
--- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundlePropertyStructureViewElement.java
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundlePropertyStructureViewElement.java
@@ -20,11 +20,8 @@
package com.intellij.lang.properties.editor;
import com.intellij.ide.structureView.StructureViewTreeElement;
-import com.intellij.lang.properties.IProperty;
-import com.intellij.lang.properties.PropertiesHighlighter;
-import com.intellij.lang.properties.PropertiesUtil;
+import com.intellij.lang.properties.*;
import com.intellij.lang.properties.ResourceBundle;
-import com.intellij.lang.properties.psi.Property;
import com.intellij.navigation.ColoredItemPresentation;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.editor.colors.EditorColorsManager;
@@ -62,7 +59,7 @@ public class ResourceBundlePropertyStructureViewElement implements StructureView
@Override
public PsiElement[] getPsiElements() {
- return new PsiElement[] {getProperty().getPsiElement()};
+ return new PsiElement[] {getValue()};
}
public void setPresentableName(final String presentableName) {
@@ -70,8 +67,8 @@ public class ResourceBundlePropertyStructureViewElement implements StructureView
}
@Override
- public Property getValue() {
- return (Property)myProperty.getPsiElement();
+ public PsiElement getValue() {
+ return myProperty.getPsiElement();
}
@Override
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertiesFileImpl.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertiesFileImpl.java
index 759ce6cb46fb..99d06e8da06b 100644
--- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertiesFileImpl.java
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertiesFileImpl.java
@@ -20,6 +20,7 @@ import com.intellij.lang.ASTFactory;
import com.intellij.lang.ASTNode;
import com.intellij.lang.properties.*;
import com.intellij.lang.properties.ResourceBundle;
+import com.intellij.lang.properties.ResourceBundleManager;
import com.intellij.lang.properties.parsing.PropertiesElementTypes;
import com.intellij.lang.properties.psi.PropertiesElementFactory;
import com.intellij.lang.properties.psi.PropertiesFile;
@@ -120,7 +121,7 @@ public class PropertiesFileImpl extends PsiFileBase implements PropertiesFile {
@Override
@NotNull
public Locale getLocale() {
- return PropertiesUtil.getLocale(getVirtualFile());
+ return ResourceBundleManager.getInstance(getProject()).getLocale(getVirtualFile());
}
@Override
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java
index 4b8953f47e9c..6c2453b94144 100644
--- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java
@@ -17,8 +17,8 @@ package com.intellij.lang.properties.xml;
import com.intellij.lang.properties.IProperty;
import com.intellij.lang.properties.PropertiesImplUtil;
-import com.intellij.lang.properties.PropertiesUtil;
import com.intellij.lang.properties.ResourceBundle;
+import com.intellij.lang.properties.ResourceBundleManager;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.lang.properties.psi.Property;
import com.intellij.openapi.project.Project;
@@ -107,7 +107,7 @@ public class XmlPropertiesFileImpl extends XmlPropertiesFile {
@NotNull
@Override
public Locale getLocale() {
- return PropertiesUtil.getLocale(getVirtualFile());
+ return ResourceBundleManager.getInstance(getProject()).getLocale(getVirtualFile());
}
@NotNull
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/properties/PropertiesCoreEnvironment.java b/plugins/properties/properties-psi-impl/src/com/intellij/properties/PropertiesCoreEnvironment.java
index f946e41c26ae..52d4d5934b40 100644
--- a/plugins/properties/properties-psi-impl/src/com/intellij/properties/PropertiesCoreEnvironment.java
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/properties/PropertiesCoreEnvironment.java
@@ -25,6 +25,7 @@ import com.intellij.lang.LanguageParserDefinitions;
import com.intellij.lang.findUsages.LanguageFindUsages;
import com.intellij.lang.folding.LanguageFolding;
import com.intellij.lang.properties.*;
+import com.intellij.lang.properties.ResourceBundleManager;
import com.intellij.lang.properties.editor.PropertiesFoldingBuilder;
import com.intellij.lang.properties.findUsages.PropertiesFindUsagesProvider;
import com.intellij.lang.properties.parsing.PropertiesElementTypes;
@@ -87,6 +88,7 @@ public class PropertiesCoreEnvironment {
public ProjectEnvironment(CoreProjectEnvironment projectEnvironment) {
projectEnvironment.getProject().registerService(PropertiesReferenceManager.class);
projectEnvironment.getProject().registerService(PropertiesSeparatorManager.class);
+ projectEnvironment.getProject().registerService(ResourceBundleManager.class);
}
}
}
diff --git a/plugins/properties/src/META-INF/plugin.xml b/plugins/properties/src/META-INF/plugin.xml
index 513678dcbf72..672add1a002d 100644
--- a/plugins/properties/src/META-INF/plugin.xml
+++ b/plugins/properties/src/META-INF/plugin.xml
@@ -34,6 +34,7 @@
implementationClass="com.intellij.lang.properties.PropertyManipulator"/>
<projectService serviceInterface="com.intellij.lang.properties.structureView.PropertiesSeparatorManager"
serviceImplementation="com.intellij.lang.properties.structureView.PropertiesSeparatorManager"/>
+ <projectService serviceImplementation="com.intellij.lang.properties.ResourceBundleManager"/>
<codeInsight.wordCompletionFilter language="Properties"
implementationClass="com.intellij.lang.properties.PropertiesWordCompletionFilter"/>
<lang.psiStructureViewFactory language="Properties"
@@ -98,6 +99,12 @@
</project-components>
<actions>
+ <action id="DissociateResourceBundleAction" class="com.intellij.lang.properties.customizeActions.DissociateResourceBundleAction">
+ <add-to-group group-id="ProjectViewPopupMenu"/>
+ </action>
+ <action id="CombinePropertiesFilesAction" class="com.intellij.lang.properties.customizeActions.CombinePropertiesFilesAction">
+ <add-to-group group-id="ProjectViewPopupMenu"/>
+ </action>
<action id="ChooseNextSubsequentPropertyValueEditorAction"
class="com.intellij.lang.properties.editor.ChooseSubsequentPropertyValueEditorAction$Next"
text="Choose Next Property Value Editor"
diff --git a/plugins/properties/src/com/intellij/lang/properties/PropertiesFilesManager.java b/plugins/properties/src/com/intellij/lang/properties/PropertiesFilesManager.java
index 60d337681a31..5477c137021e 100644
--- a/plugins/properties/src/com/intellij/lang/properties/PropertiesFilesManager.java
+++ b/plugins/properties/src/com/intellij/lang/properties/PropertiesFilesManager.java
@@ -20,7 +20,7 @@ import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.encoding.EncodingManager;
import com.intellij.psi.search.FileTypeIndex;
@@ -44,20 +44,24 @@ public class PropertiesFilesManager extends AbstractProjectComponent {
super(project);
}
+ @Override
public void projectOpened() {
final PropertyChangeListener myListener = new PropertyChangeListener() {
+ @Override
public void propertyChange(final PropertyChangeEvent evt) {
String propertyName = evt.getPropertyName();
if (EncodingManager.PROP_NATIVE2ASCII_SWITCH.equals(propertyName) ||
EncodingManager.PROP_PROPERTIES_FILES_ENCODING.equals(propertyName)
) {
DumbService.getInstance(myProject).smartInvokeLater(new Runnable(){
+ @Override
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable(){
+ @Override
public void run() {
Collection<VirtualFile> filesToRefresh = FileBasedIndex.getInstance()
.getContainingFiles(FileTypeIndex.NAME, PropertiesFileType.INSTANCE, GlobalSearchScope.allScope(myProject));
- VirtualFile[] virtualFiles = VfsUtil.toVirtualFileArray(filesToRefresh);
+ VirtualFile[] virtualFiles = VfsUtilCore.toVirtualFileArray(filesToRefresh);
FileDocumentManager.getInstance().saveAllDocuments();
//force to re-detect encoding
@@ -75,6 +79,7 @@ public class PropertiesFilesManager extends AbstractProjectComponent {
EncodingManager.getInstance().addPropertyChangeListener(myListener,myProject);
}
+ @Override
@NotNull
public String getComponentName() {
return "PropertiesFileManager";
diff --git a/plugins/properties/src/com/intellij/lang/properties/ResourceBundleReference.java b/plugins/properties/src/com/intellij/lang/properties/ResourceBundleReference.java
index 5f708c3eda61..14ac858d9917 100644
--- a/plugins/properties/src/com/intellij/lang/properties/ResourceBundleReference.java
+++ b/plugins/properties/src/com/intellij/lang/properties/ResourceBundleReference.java
@@ -97,14 +97,14 @@ public class ResourceBundleReference extends PsiReferenceBase<PsiElement> implem
if (!(element instanceof PropertiesFile)) {
throw new IncorrectOperationException();
}
- final String name = PropertiesUtil.getFullName((PropertiesFile)element);
+ final String name = ResourceBundleManager.getInstance(element.getProject()).getFullName((PropertiesFile)element);
return super.handleElementRename(name);
}
public boolean isReferenceTo(PsiElement element) {
if (element instanceof PropertiesFile) {
- final String name = PropertiesUtil.getFullName((PropertiesFile)element);
+ final String name = ResourceBundleManager.getInstance(element.getProject()).getFullName((PropertiesFile)element);
if (name != null && name.equals(myBundleName)) {
return true;
}
diff --git a/plugins/properties/src/com/intellij/lang/properties/customizeActions/CombinePropertiesFilesAction.java b/plugins/properties/src/com/intellij/lang/properties/customizeActions/CombinePropertiesFilesAction.java
new file mode 100644
index 000000000000..b90e74a2c767
--- /dev/null
+++ b/plugins/properties/src/com/intellij/lang/properties/customizeActions/CombinePropertiesFilesAction.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.properties.customizeActions;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.projectView.ProjectView;
+import com.intellij.lang.properties.PropertiesBundle;
+import com.intellij.lang.properties.PropertiesImplUtil;
+import com.intellij.lang.properties.PropertiesUtil;
+import com.intellij.lang.properties.ResourceBundle;
+import com.intellij.lang.properties.ResourceBundleManager;
+import com.intellij.lang.properties.editor.ResourceBundleAsVirtualFile;
+import com.intellij.lang.properties.psi.PropertiesFile;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.LangDataKeys;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.InputValidatorEx;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class CombinePropertiesFilesAction extends AnAction {
+
+ public CombinePropertiesFilesAction() {
+ super(PropertiesBundle.message("combine.properties.files.title"), null, AllIcons.FileTypes.Properties);
+ }
+
+ @Override
+ public void actionPerformed(final AnActionEvent e) {
+ final List<PropertiesFile> propertiesFiles = getPropertiesFiles(e);
+ final String newBaseName = Messages.showInputDialog(propertiesFiles.get(0).getProject(),
+ PropertiesBundle.message("combine.properties.files.prompt.text"),
+ PropertiesBundle.message("combine.properties.files.title"),
+ Messages.getQuestionIcon(),
+ PropertiesUtil.getDefaultBaseName(propertiesFiles),
+ new MyInputValidator(propertiesFiles));
+ if (newBaseName != null) {
+ final Project project = propertiesFiles.get(0).getProject();
+ ResourceBundleManager.getInstance(project).combineToResourceBundle(propertiesFiles, newBaseName);
+ final ResourceBundle resourceBundle = propertiesFiles.get(0).getResourceBundle();
+ FileEditorManager.getInstance(project).openFile(new ResourceBundleAsVirtualFile(resourceBundle), true);
+ ProjectView.getInstance(project).refresh();
+ }
+ }
+
+ @Override
+ public void update(final AnActionEvent e) {
+ final List<PropertiesFile> propertiesFiles = getPropertiesFiles(e);
+ boolean isAvailable = propertiesFiles != null && propertiesFiles.size() > 1;
+ if (isAvailable) {
+ for (PropertiesFile propertiesFile : propertiesFiles) {
+ if (propertiesFile.getResourceBundle().getPropertiesFiles().size() != 1) {
+ isAvailable = false;
+ break;
+ }
+ }
+ }
+ e.getPresentation().setVisible(isAvailable);
+ }
+
+ @Nullable
+ private static List<PropertiesFile> getPropertiesFiles(AnActionEvent e) {
+ final PsiElement[] psiElements = e.getData(LangDataKeys.PSI_ELEMENT_ARRAY);
+ if (psiElements == null || psiElements.length == 0) {
+ return null;
+ }
+ final List<PropertiesFile> files = new ArrayList<PropertiesFile>(psiElements.length);
+ for (PsiElement psiElement : psiElements) {
+ if (!(psiElement instanceof PsiFile)) {
+ return null;
+ }
+ final PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile((PsiFile)psiElement);
+ if (propertiesFile == null) {
+ return null;
+ }
+ files.add(propertiesFile);
+ }
+ return files;
+ }
+
+ @Override
+ public boolean isDumbAware() {
+ return true;
+ }
+
+ private static class MyInputValidator implements InputValidatorEx {
+ private final List<PropertiesFile> myPropertiesFiles;
+
+ private MyInputValidator(final List<PropertiesFile> propertiesFiles) {
+ myPropertiesFiles = propertiesFiles;
+ }
+
+ @Override
+ public boolean checkInput(final String newBaseName) {
+ return !newBaseName.isEmpty() && checkBaseName(newBaseName) == null;
+ }
+
+ @Override
+ public boolean canClose(final String newBaseName) {
+ return true;
+ }
+
+ @Nullable
+ @Override
+ public String getErrorText(String inputString) {
+ return checkInput(inputString) ? null : String.format("Base name must be valid for file \'%s\'", checkBaseName(inputString).getFailedFile());
+ }
+
+ @Nullable
+ private BaseNameError checkBaseName(final String baseNameCandidate) {
+ for (PropertiesFile propertiesFile : myPropertiesFiles) {
+ final String name = propertiesFile.getVirtualFile().getName();
+ if (!name.startsWith(baseNameCandidate) || !PropertiesUtil.BASE_NAME_BORDER_CHAR.contains(name.charAt(baseNameCandidate.length()))) {
+ return new BaseNameError(name);
+ }
+ }
+ return null;
+ }
+
+ private static class BaseNameError {
+
+ private final String myFailedFile;
+
+ private BaseNameError(String failedFile) {
+ myFailedFile = failedFile;
+ }
+
+ public String getFailedFile() {
+ return myFailedFile;
+ }
+ }
+ }
+}
diff --git a/plugins/properties/src/com/intellij/lang/properties/customizeActions/DissociateResourceBundleAction.java b/plugins/properties/src/com/intellij/lang/properties/customizeActions/DissociateResourceBundleAction.java
new file mode 100644
index 000000000000..10041448d97c
--- /dev/null
+++ b/plugins/properties/src/com/intellij/lang/properties/customizeActions/DissociateResourceBundleAction.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.properties.customizeActions;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.projectView.ProjectView;
+import com.intellij.lang.properties.PropertiesImplUtil;
+import com.intellij.lang.properties.ResourceBundle;
+import com.intellij.lang.properties.ResourceBundleManager;
+import com.intellij.lang.properties.editor.ResourceBundleAsVirtualFile;
+import com.intellij.lang.properties.psi.PropertiesFile;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class DissociateResourceBundleAction extends AnAction {
+ private static final String PRESENTATION_TEXT_TEMPLATE = "Dissociate Resource Bundle '%s'";
+
+ public DissociateResourceBundleAction() {
+ super(null, null, AllIcons.FileTypes.Properties);
+ }
+
+ @Override
+ public void actionPerformed(final AnActionEvent e) {
+ final ResourceBundle resourceBundle = extractResourceBundle(e);
+ assert resourceBundle != null;
+ final Project project = resourceBundle.getProject();
+ final FileEditorManager fileEditorManager = FileEditorManager.getInstance(project);
+ fileEditorManager.closeFile(new ResourceBundleAsVirtualFile(resourceBundle));
+ for (final PropertiesFile propertiesFile : resourceBundle.getPropertiesFiles()) {
+ fileEditorManager.closeFile(propertiesFile.getVirtualFile());
+ }
+ ResourceBundleManager.getInstance(e.getProject()).dissociateResourceBundle(resourceBundle);
+ ProjectView.getInstance(project).refresh();
+ }
+
+ @Override
+ public void update(final AnActionEvent e) {
+ final ResourceBundle resourceBundle = extractResourceBundle(e);
+ if (resourceBundle != null) {
+ e.getPresentation().setText(String.format(PRESENTATION_TEXT_TEMPLATE, resourceBundle.getBaseName()), false);
+ e.getPresentation().setVisible(true);
+ } else {
+ e.getPresentation().setVisible(false);
+ }
+ }
+
+ @Nullable
+ private static ResourceBundle extractResourceBundle(final AnActionEvent event) {
+ final ResourceBundle[] data = event.getData(ResourceBundle.ARRAY_DATA_KEY);
+ if (data != null && data.length == 1 && data[0].getPropertiesFiles().size() > 1) {
+ return data[0];
+ }
+ final PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(event.getData(PlatformDataKeys.PSI_FILE));
+ if (propertiesFile == null) {
+ return null;
+ }
+ final ResourceBundle resourceBundle = propertiesFile.getResourceBundle();
+ return resourceBundle.getPropertiesFiles().size() > 1 ? resourceBundle : null;
+ }
+}
diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java
index 36915e7e6962..bae39bd9f2d0 100644
--- a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java
+++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java
@@ -23,14 +23,10 @@ import com.intellij.ide.presentation.Presentation;
import com.intellij.lang.properties.PropertiesImplUtil;
import com.intellij.lang.properties.PropertiesUtil;
import com.intellij.lang.properties.ResourceBundle;
-import com.intellij.lang.properties.psi.PropertiesFile;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileSystem;
-import com.intellij.psi.PsiManager;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.io.InputStream;
@@ -38,25 +34,15 @@ import java.io.OutputStream;
@Presentation(icon = "AllIcons.Nodes.ResourceBundle")
public class ResourceBundleAsVirtualFile extends VirtualFile {
- private final VirtualFile myBasePropertiesFile;
+ private final ResourceBundle myResourceBundle;
- private ResourceBundleAsVirtualFile(@NotNull final VirtualFile basePropertiesFile) {
- myBasePropertiesFile = basePropertiesFile;
+ public ResourceBundleAsVirtualFile(@NotNull final ResourceBundle resourceBundle) {
+ myResourceBundle = resourceBundle;
}
@NotNull
- public static ResourceBundleAsVirtualFile fromResourceBundle(final @NotNull ResourceBundle resourceBundle) {
- return new ResourceBundleAsVirtualFile(resourceBundle.getDefaultPropertiesFile().getVirtualFile());
- }
-
- @Nullable
- public ResourceBundle getResourceBundle(final Project project) {
- final PsiManager psiManager = PsiManager.getInstance(project);
- final PropertiesFile file = PropertiesImplUtil.getPropertiesFile(psiManager.findFile(myBasePropertiesFile));
- if (file == null) {
- return null;
- }
- return PropertiesImplUtil.getResourceBundle(file);
+ public ResourceBundle getResourceBundle() {
+ return myResourceBundle;
}
@Override
@@ -74,7 +60,7 @@ public class ResourceBundleAsVirtualFile extends VirtualFile {
@Override
@NotNull
public String getName() {
- return PropertiesUtil.getBaseName(myBasePropertiesFile);
+ return myResourceBundle.getBaseName();
}
public boolean equals(final Object o) {
@@ -83,13 +69,13 @@ public class ResourceBundleAsVirtualFile extends VirtualFile {
final ResourceBundleAsVirtualFile resourceBundleAsVirtualFile = (ResourceBundleAsVirtualFile)o;
- if (!myBasePropertiesFile.equals(resourceBundleAsVirtualFile.myBasePropertiesFile)) return false;
+ if (!myResourceBundle.equals(resourceBundleAsVirtualFile.myResourceBundle)) return false;
return true;
}
public int hashCode() {
- return myBasePropertiesFile.hashCode();
+ return myResourceBundle.hashCode();
}
@Override
@@ -114,7 +100,7 @@ public class ResourceBundleAsVirtualFile extends VirtualFile {
@Override
public VirtualFile getParent() {
- return myBasePropertiesFile.getParent();
+ return myResourceBundle.getBaseDirectory();
}
@Override
diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java
index 39e9ed67e7b2..27deebbff2af 100644
--- a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java
+++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java
@@ -170,7 +170,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
TreeElement[] children = myStructureViewComponent.getTreeModel().getRoot().getChildren();
if (children.length != 0) {
TreeElement child = children[0];
- String propName = ((ResourceBundlePropertyStructureViewElement)child).getValue().getUnescapedKey();
+ String propName = ((ResourceBundlePropertyStructureViewElement)child).getProperty().getUnescapedKey();
setState(new ResourceBundleEditorState(propName));
}
myDataProviderPanel = new DataProviderPanel(splitPanel);
@@ -248,7 +248,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
DefaultMutableTreeNode node = toCheck.pop();
final ResourceBundleEditorViewElement element = getSelectedElement(node);
String value = element instanceof ResourceBundlePropertyStructureViewElement
- ? ((ResourceBundlePropertyStructureViewElement)element).getValue().getUnescapedKey()
+ ? ((ResourceBundlePropertyStructureViewElement)element).getProperty().getUnescapedKey()
: null;
if (propertyName.equals(value)) {
nodeToSelect = node;
diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditorProvider.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditorProvider.java
index fdbc2c0c5e59..d70dd358a9a9 100644
--- a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditorProvider.java
+++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditorProvider.java
@@ -50,7 +50,7 @@ public class ResourceBundleEditorProvider extends FileTypeFactory implements Fil
public FileEditor createEditor(@NotNull Project project, @NotNull final VirtualFile file){
ResourceBundle resourceBundle;
if (file instanceof ResourceBundleAsVirtualFile) {
- resourceBundle = ((ResourceBundleAsVirtualFile)file).getResourceBundle(project);
+ resourceBundle = ((ResourceBundleAsVirtualFile)file).getResourceBundle();
}
else {
PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleStructureViewComponent.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleStructureViewComponent.java
index da376abe05b2..f950f613ecb9 100644
--- a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleStructureViewComponent.java
+++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleStructureViewComponent.java
@@ -72,7 +72,7 @@ class ResourceBundleStructureViewComponent extends PropertiesGroupingStructureVi
public Object getData(final String dataId) {
if (CommonDataKeys.VIRTUAL_FILE.is(dataId)) {
- return ResourceBundleAsVirtualFile.fromResourceBundle(myResourceBundle);
+ return new ResourceBundleAsVirtualFile(myResourceBundle);
} else if (PlatformDataKeys.FILE_EDITOR.is(dataId)) {
return getFileEditor();
} else if (LangDataKeys.PSI_ELEMENT_ARRAY.is(dataId)) {
diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleUtil.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleUtil.java
index e4a35e7e677c..51c3764b7f2e 100644
--- a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleUtil.java
+++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleUtil.java
@@ -56,7 +56,7 @@ public class ResourceBundleUtil {
}
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (virtualFile instanceof ResourceBundleAsVirtualFile && project != null) {
- return ((ResourceBundleAsVirtualFile)virtualFile).getResourceBundle(project);
+ return ((ResourceBundleAsVirtualFile)virtualFile).getResourceBundle();
}
if (project != null) {
final PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile);
diff --git a/plugins/properties/src/com/intellij/lang/properties/projectView/CustomResourceBundlePropertiesFileNode.java b/plugins/properties/src/com/intellij/lang/properties/projectView/CustomResourceBundlePropertiesFileNode.java
new file mode 100644
index 000000000000..605b8c843a47
--- /dev/null
+++ b/plugins/properties/src/com/intellij/lang/properties/projectView/CustomResourceBundlePropertiesFileNode.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.properties.projectView;
+
+import com.intellij.ide.projectView.PresentationData;
+import com.intellij.ide.projectView.ViewSettings;
+import com.intellij.ide.projectView.impl.nodes.PsiFileNode;
+import com.intellij.lang.properties.PropertiesBundle;
+import com.intellij.lang.properties.PropertiesImplUtil;
+import com.intellij.lang.properties.ResourceBundle;
+import com.intellij.lang.properties.psi.PropertiesFile;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.ui.SimpleTextAttributes;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class CustomResourceBundlePropertiesFileNode extends PsiFileNode {
+ public CustomResourceBundlePropertiesFileNode(Project project, PsiFile value, ViewSettings viewSettings) {
+ super(project, value, viewSettings);
+ setUpdateCount(-1);
+ }
+
+ @Override
+ public void update(PresentationData data) {
+ super.update(data);
+ final PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(getValue());
+ assert propertiesFile != null;
+ final ResourceBundle resourceBundle = propertiesFile.getResourceBundle();
+ data.setLocationString(PropertiesBundle.message("project.view.resource.bundle.tree.node.text", resourceBundle.getBaseName()));
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (!(object instanceof CustomResourceBundlePropertiesFileNode)) {
+ return false;
+ }
+ return Comparing.equal(getValue(), ((CustomResourceBundlePropertiesFileNode)object).getValue());
+ }
+}
diff --git a/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleGrouper.java b/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleGrouper.java
index 0ac072c062c2..f6f268df3597 100644
--- a/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleGrouper.java
+++ b/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleGrouper.java
@@ -18,6 +18,7 @@ package com.intellij.lang.properties.projectView;
import com.intellij.ide.projectView.TreeStructureProvider;
import com.intellij.ide.projectView.ViewSettings;
import com.intellij.ide.util.treeView.AbstractTreeNode;
+import com.intellij.lang.properties.CustomResourceBundle;
import com.intellij.lang.properties.PropertiesImplUtil;
import com.intellij.lang.properties.ResourceBundle;
import com.intellij.lang.properties.psi.PropertiesFile;
@@ -83,6 +84,10 @@ public class ResourceBundleGrouper implements TreeStructureProvider, DumbAware {
ResourceBundle bundle = propertiesFile.getResourceBundle();
if (childBundles.get(bundle).size() != 1) {
continue;
+ } else if (bundle instanceof CustomResourceBundle) {
+ final CustomResourceBundlePropertiesFileNode node =
+ new CustomResourceBundlePropertiesFileNode(myProject, (PsiFile)f, settings);
+ result.add(node);
}
}
}
diff --git a/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleNode.java b/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleNode.java
index a415e4544aa0..b9f61643095d 100644
--- a/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleNode.java
+++ b/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleNode.java
@@ -86,7 +86,7 @@ public class ResourceBundleNode extends ProjectViewNode<ResourceBundle>{
}
public void navigate(final boolean requestFocus) {
- OpenFileDescriptor descriptor = new OpenFileDescriptor(getProject(), ResourceBundleAsVirtualFile.fromResourceBundle(getValue()));
+ OpenFileDescriptor descriptor = new OpenFileDescriptor(getProject(), new ResourceBundleAsVirtualFile(getValue()));
FileEditorManager.getInstance(getProject()).openTextEditor(descriptor, requestFocus);
}
diff --git a/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/RenamePropertyProcessor.java b/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/RenamePropertyProcessor.java
index f3c81736673f..6f0d52f1c294 100644
--- a/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/RenamePropertyProcessor.java
+++ b/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/RenamePropertyProcessor.java
@@ -46,7 +46,7 @@ public class RenamePropertyProcessor extends RenamePsiElementProcessor {
allRenames.clear();
for (final Map.Entry<PsiElement, String> e : allRenamesCopy.entrySet()) {
final IProperty property = (IProperty) e.getKey();
- final List<IProperty> properties = PropertiesUtil.findAllProperties(project, resourceBundle, property.getUnescapedKey());
+ final List<IProperty> properties = PropertiesUtil.findAllProperties(resourceBundle, property.getUnescapedKey());
for (final IProperty toRename : properties) {
allRenames.put(toRename.getPsiElement(), e.getValue());
}
diff --git a/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/ResourceBundleRenamer.java b/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/ResourceBundleRenamer.java
index ab1b4391b0f6..000f72ef5ae3 100644
--- a/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/ResourceBundleRenamer.java
+++ b/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/ResourceBundleRenamer.java
@@ -16,7 +16,7 @@
package com.intellij.lang.properties.refactoring.rename;
import com.intellij.lang.properties.PropertiesBundle;
-import com.intellij.lang.properties.PropertiesUtil;
+import com.intellij.lang.properties.ResourceBundleManager;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiNamedElement;
@@ -28,7 +28,10 @@ import org.jetbrains.annotations.NonNls;
*/
public class ResourceBundleRenamer extends AutomaticRenamer {
+ private final ResourceBundleManager myResourceBundleManager;
+
public ResourceBundleRenamer(final PropertiesFile propertiesFile, final String newName) {
+ myResourceBundleManager = ResourceBundleManager.getInstance(propertiesFile.getProject());
for (final PropertiesFile file : propertiesFile.getResourceBundle().getPropertiesFiles()) {
if (file.equals(propertiesFile)) {
continue;
@@ -41,12 +44,12 @@ public class ResourceBundleRenamer extends AutomaticRenamer {
@Override
protected String nameToCanonicalName(@NonNls final String name, final PsiNamedElement element) {
- return PropertiesUtil.getBaseName((PsiFile)element);
+ return myResourceBundleManager.getBaseName((PsiFile)element);
}
@Override
protected String canonicalNameToName(@NonNls final String canonicalName, final PsiNamedElement element) {
- final String oldCanonicalName = PropertiesUtil.getBaseName((PsiFile)element);
+ final String oldCanonicalName = myResourceBundleManager.getBaseName((PsiFile)element);
final String oldName = element.getName();
assert oldName != null;
return canonicalName + oldName.substring(oldCanonicalName.length());
diff --git a/plugins/properties/testSrc/com/intellij/lang/properties/CustomResourceBundleTest.java b/plugins/properties/testSrc/com/intellij/lang/properties/CustomResourceBundleTest.java
new file mode 100644
index 000000000000..69e8621ac8db
--- /dev/null
+++ b/plugins/properties/testSrc/com/intellij/lang/properties/CustomResourceBundleTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.properties;
+
+import com.intellij.lang.properties.psi.PropertiesFile;
+import com.intellij.psi.PsiDirectory;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesProcessor;
+import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import static com.intellij.util.containers.ContainerUtil.list;
+import static com.intellij.util.containers.ContainerUtil.map;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class CustomResourceBundleTest extends LightPlatformCodeInsightFixtureTestCase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ ResourceBundleManager.getInstance(getProject()).loadState(new ResourceBundleManagerState());
+ }
+
+ public void testDissociateDefaultBaseName() {
+ final PsiFile file = myFixture.addFileToProject("some_property_file.properties", "");
+ final PsiFile file2 = myFixture.addFileToProject("some_property_filee.properties", "");
+ final PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(file);
+ assertNotNull(propertiesFile);
+ final ResourceBundle resourceBundle = propertiesFile.getResourceBundle();
+ final ResourceBundleManager resourceBundleBaseNameManager = ResourceBundleManager.getInstance(getProject());
+ resourceBundleBaseNameManager.dissociateResourceBundle(resourceBundle);
+ for (final PsiFile psiFile : list(file, file2)) {
+ assertEquals(psiFile.getVirtualFile().getNameWithoutExtension(), resourceBundleBaseNameManager.getBaseName(psiFile));
+ final PropertiesFile somePropertyFile = PropertiesImplUtil.getPropertiesFile(file);
+ assertNotNull(somePropertyFile);
+ assertOneElement(somePropertyFile.getResourceBundle().getPropertiesFiles());
+ }
+ }
+
+ public void testCombineToCustomResourceBundleAndDissociateAfter() {
+ final PropertiesFile file = PropertiesImplUtil.getPropertiesFile(myFixture.addFileToProject("resources-dev/my-app-dev.properties", ""));
+ final PropertiesFile file2 = PropertiesImplUtil.getPropertiesFile(myFixture.addFileToProject("resources-prod/my-app-prod.properties", ""));
+ assertNotNull(file);
+ assertNotNull(file2);
+ assertOneElement(file.getResourceBundle().getPropertiesFiles());
+ assertOneElement(file2.getResourceBundle().getPropertiesFiles());
+
+ final ResourceBundleManager resourceBundleBaseNameManager = ResourceBundleManager.getInstance(getProject());
+ final String newBaseName = "my-app";
+ resourceBundleBaseNameManager.combineToResourceBundle(list(file, file2), newBaseName);
+ final ResourceBundle resourceBundle = file.getResourceBundle();
+ assertEquals(2, resourceBundle.getPropertiesFiles().size());
+ assertEquals(newBaseName, resourceBundle.getBaseName());
+
+ resourceBundleBaseNameManager.dissociateResourceBundle(resourceBundle);
+ assertOneElement(file.getResourceBundle().getPropertiesFiles());
+ assertOneElement(file2.getResourceBundle().getPropertiesFiles());
+ }
+
+ public void testCustomResourceBundleFilesMovedOrDeleted() throws IOException {
+ final PropertiesFile file = PropertiesImplUtil.getPropertiesFile(myFixture.addFileToProject("resources-dev/my-app-dev.properties", ""));
+ final PropertiesFile file2 = PropertiesImplUtil.getPropertiesFile(myFixture.addFileToProject("resources-dev/my-app-test.properties", ""));
+ final PropertiesFile file3 = PropertiesImplUtil.getPropertiesFile(myFixture.addFileToProject("resources-prod/my-app-prod.properties", ""));
+ assertNotNull(file);
+ assertNotNull(file2);
+ assertNotNull(file3);
+ assertOneElement(file.getResourceBundle().getPropertiesFiles());
+ assertOneElement(file2.getResourceBundle().getPropertiesFiles());
+ assertOneElement(file3.getResourceBundle().getPropertiesFiles());
+ final ResourceBundleManager resourceBundleBaseNameManager = ResourceBundleManager.getInstance(getProject());
+ resourceBundleBaseNameManager.combineToResourceBundle(list(file, file2, file3), "my-app");
+
+ assertSize(3, file.getResourceBundle().getPropertiesFiles());
+
+ final PsiDirectory newDir = PsiManager.getInstance(getProject()).findDirectory(myFixture.getTempDirFixture().findOrCreateDir("new-resources-dir"));
+ new MoveFilesOrDirectoriesProcessor(getProject(), new PsiElement[] {file2.getContainingFile()}, newDir, false, false, null, null).run();
+ file3.getContainingFile().delete();
+
+ assertSize(2, file.getResourceBundle().getPropertiesFiles());
+
+ final ResourceBundleManagerState state = ResourceBundleManager.getInstance(getProject()).getState();
+ assertNotNull(state);
+ assertSize(1, state.getCustomResourceBundles());
+ assertSize(2, state.getCustomResourceBundles().get(0).getFileUrls());
+ }
+
+ public void testLocaleIfCanExtractFromCustomResourceBundle() {
+ final PsiFile file = myFixture.addFileToProject("Base_Page.properties", "");
+ final PsiFile file2 = myFixture.addFileToProject("Base_Page_en.properties", "");
+ final ResourceBundleManager resourceBundleBaseNameManager = ResourceBundleManager.getInstance(getProject());
+ final PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(file);
+ assertNotNull(propertiesFile);
+ resourceBundleBaseNameManager.dissociateResourceBundle(propertiesFile.getResourceBundle());
+ resourceBundleBaseNameManager.combineToResourceBundle(map(list(file, file2), new Function<PsiFile, PropertiesFile>() {
+ @Override
+ public PropertiesFile fun(final PsiFile psiFile) {
+ return PropertiesImplUtil.getPropertiesFile(psiFile);
+ }
+ }), "Base_Page");
+ final PropertiesFile propertiesFile2 = PropertiesImplUtil.getPropertiesFile(file2);
+ assertNotNull(propertiesFile2);
+ final Locale locale = propertiesFile2.getLocale();
+ assertEquals("en", locale.getLanguage());
+ }
+
+ public void testSuggestedCustomResourceBundleName() {
+ final PsiFile file = myFixture.addFileToProject("Base_Page.properties", "");
+ final PsiFile file2 = myFixture.addFileToProject("Base_Page_en.properties", "");
+ final String baseName =
+ PropertiesUtil.getDefaultBaseName(ContainerUtil.map(list(file, file2), new Function<PsiFile, PropertiesFile>() {
+ @Override
+ public PropertiesFile fun(PsiFile psiFile) {
+ return PropertiesImplUtil.getPropertiesFile(file);
+ }
+ }));
+ assertEquals("Base_Page", baseName);
+ }
+}
diff --git a/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesUtilTest.java b/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesUtilTest.java
index 20c44e9f47e0..44765f96fc69 100644
--- a/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesUtilTest.java
+++ b/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesUtilTest.java
@@ -15,12 +15,7 @@
*/
package com.intellij.lang.properties;
-import com.intellij.openapi.vfs.newvfs.impl.StubVirtualFile;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.impl.FakePsiElement;
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
-import junit.framework.TestCase;
-import org.jetbrains.annotations.NotNull;
/**
* @author Dmitry Batkovich
@@ -59,18 +54,8 @@ public class PropertiesUtilTest extends LightPlatformCodeInsightFixtureTestCase
assertBaseNameEquals("Base_Properties.utf8.properties", "Base_Properties.utf8");
}
- public void _test1() {
- assertBaseNameEquals("Base_Page_fr.utf8.properties", "Base_Page.utf8");
- }
- public void _test2() {
- assertBaseNameEquals("Base_Page_en.utf8.properties", "Base_Page.utf8");
- }
- public void _test3() {
- assertBaseNameEquals("Base_Page.utf8.properties", "Base_Page.utf8");
- }
-
private void assertBaseNameEquals(final String propertyFileName, final String expectedBaseName) {
- final String actualBaseName = PropertiesUtil.getBaseName(myFixture.configureByText(propertyFileName, ""));
+ final String actualBaseName = ResourceBundleManager.getInstance(getProject()).getBaseName(myFixture.configureByText(propertyFileName, ""));
assertEquals(expectedBaseName, actualBaseName);
}
}