improve exception handling on syntax errors
Resolves #167 Resolves #177
This commit is contained in:
parent
38f5bcb900
commit
150f40d395
@ -3,6 +3,9 @@
|
|||||||
# easy-i18n Changelog
|
# easy-i18n Changelog
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
### Changed
|
||||||
|
- Improved exception handling on syntax errors
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Some settings are not retained on IDE restarts
|
- Some settings are not retained on IDE restarts
|
||||||
|
|
||||||
|
37
src/main/java/de/marhali/easyi18n/action/OpenFileAction.java
Normal file
37
src/main/java/de/marhali/easyi18n/action/OpenFileAction.java
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package de.marhali.easyi18n.action;
|
||||||
|
|
||||||
|
import com.intellij.icons.AllIcons;
|
||||||
|
import com.intellij.openapi.actionSystem.AnAction;
|
||||||
|
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||||
|
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin action to open a specific file.
|
||||||
|
* @author marhali
|
||||||
|
*/
|
||||||
|
public class OpenFileAction extends AnAction {
|
||||||
|
private final VirtualFile file;
|
||||||
|
|
||||||
|
public OpenFileAction(VirtualFile file) {
|
||||||
|
this(file, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OpenFileAction(VirtualFile file, boolean showIcon) {
|
||||||
|
super(ResourceBundle.getBundle("messages").getString("action.file"),
|
||||||
|
null, showIcon ? AllIcons.FileTypes.Any_type : null);
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||||
|
Project project = Objects.requireNonNull(e.getProject());
|
||||||
|
FileEditorManager.getInstance(project).openFile(file, true, true);
|
||||||
|
}
|
||||||
|
}
|
@ -18,8 +18,12 @@ import java.util.ResourceBundle;
|
|||||||
public class SettingsAction extends AnAction {
|
public class SettingsAction extends AnAction {
|
||||||
|
|
||||||
public SettingsAction() {
|
public SettingsAction() {
|
||||||
|
this(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SettingsAction(boolean showIcon) {
|
||||||
super(ResourceBundle.getBundle("messages").getString("action.settings"),
|
super(ResourceBundle.getBundle("messages").getString("action.settings"),
|
||||||
null, AllIcons.General.Settings);
|
null, showIcon ? AllIcons.General.Settings : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
package de.marhali.easyi18n.exception;
|
||||||
|
|
||||||
|
import de.marhali.easyi18n.model.TranslationFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates a syntax error in a managed translation file.
|
||||||
|
* @author marhali
|
||||||
|
*/
|
||||||
|
public class SyntaxException extends RuntimeException {
|
||||||
|
private final TranslationFile file;
|
||||||
|
|
||||||
|
public SyntaxException(String message, TranslationFile file) {
|
||||||
|
super(message);
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TranslationFile getFile() {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
}
|
@ -10,12 +10,14 @@ import com.intellij.openapi.vfs.VirtualFile;
|
|||||||
import com.intellij.psi.PsiDocumentManager;
|
import com.intellij.psi.PsiDocumentManager;
|
||||||
import com.intellij.psi.PsiFile;
|
import com.intellij.psi.PsiFile;
|
||||||
import de.marhali.easyi18n.exception.EmptyLocalesDirException;
|
import de.marhali.easyi18n.exception.EmptyLocalesDirException;
|
||||||
|
import de.marhali.easyi18n.exception.SyntaxException;
|
||||||
import de.marhali.easyi18n.io.folder.FolderStrategy;
|
import de.marhali.easyi18n.io.folder.FolderStrategy;
|
||||||
import de.marhali.easyi18n.io.parser.ParserStrategy;
|
import de.marhali.easyi18n.io.parser.ParserStrategy;
|
||||||
import de.marhali.easyi18n.io.parser.ParserStrategyType;
|
import de.marhali.easyi18n.io.parser.ParserStrategyType;
|
||||||
import de.marhali.easyi18n.model.*;
|
import de.marhali.easyi18n.model.*;
|
||||||
|
|
||||||
import de.marhali.easyi18n.settings.ProjectSettings;
|
import de.marhali.easyi18n.settings.ProjectSettings;
|
||||||
|
import de.marhali.easyi18n.util.NotificationHelper;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -73,6 +75,8 @@ public class IOHandler {
|
|||||||
for(TranslationFile file : translationFiles) {
|
for(TranslationFile file : translationFiles) {
|
||||||
try {
|
try {
|
||||||
this.parserStrategy.read(file, data);
|
this.parserStrategy.read(file, data);
|
||||||
|
} catch (SyntaxException ex) {
|
||||||
|
NotificationHelper.createBadSyntaxNotification(project, ex);
|
||||||
} catch(Exception ex) {
|
} catch(Exception ex) {
|
||||||
throw new IOException(file + "\n\n" + ex.getMessage(), ex);
|
throw new IOException(file + "\n\n" + ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,10 @@ import com.google.gson.Gson;
|
|||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.intellij.openapi.vfs.VirtualFile;
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
|
|
||||||
|
import de.marhali.easyi18n.exception.SyntaxException;
|
||||||
import de.marhali.easyi18n.io.parser.ParserStrategy;
|
import de.marhali.easyi18n.io.parser.ParserStrategy;
|
||||||
import de.marhali.easyi18n.model.*;
|
import de.marhali.easyi18n.model.*;
|
||||||
import de.marhali.easyi18n.settings.ProjectSettings;
|
import de.marhali.easyi18n.settings.ProjectSettings;
|
||||||
@ -36,7 +38,14 @@ public class JsonParserStrategy extends ParserStrategy {
|
|||||||
TranslationNode targetNode = super.getOrCreateTargetNode(file, data);
|
TranslationNode targetNode = super.getOrCreateTargetNode(file, data);
|
||||||
|
|
||||||
try(Reader reader = new InputStreamReader(vf.getInputStream(), vf.getCharset())) {
|
try(Reader reader = new InputStreamReader(vf.getInputStream(), vf.getCharset())) {
|
||||||
JsonObject input = GSON.fromJson(reader, JsonObject.class);
|
JsonObject input;
|
||||||
|
|
||||||
|
try {
|
||||||
|
input = GSON.fromJson(reader, JsonObject.class);
|
||||||
|
} catch (JsonSyntaxException ex) {
|
||||||
|
throw new SyntaxException(ex.getMessage(), file);
|
||||||
|
}
|
||||||
|
|
||||||
if(input != null) { // @input is null if file is completely empty
|
if(input != null) { // @input is null if file is completely empty
|
||||||
JsonMapper.read(file.getLocale(), input, targetNode);
|
JsonMapper.read(file.getLocale(), input, targetNode);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package de.marhali.easyi18n.io.parser.json5;
|
|||||||
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile;
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
|
|
||||||
|
import de.marhali.easyi18n.exception.SyntaxException;
|
||||||
import de.marhali.easyi18n.io.parser.ParserStrategy;
|
import de.marhali.easyi18n.io.parser.ParserStrategy;
|
||||||
import de.marhali.easyi18n.model.TranslationData;
|
import de.marhali.easyi18n.model.TranslationData;
|
||||||
import de.marhali.easyi18n.model.TranslationFile;
|
import de.marhali.easyi18n.model.TranslationFile;
|
||||||
@ -11,6 +12,7 @@ import de.marhali.json5.Json5;
|
|||||||
import de.marhali.json5.Json5Element;
|
import de.marhali.json5.Json5Element;
|
||||||
import de.marhali.json5.Json5Object;
|
import de.marhali.json5.Json5Object;
|
||||||
|
|
||||||
|
import de.marhali.json5.exception.Json5Exception;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
@ -38,8 +40,18 @@ public class Json5ParserStrategy extends ParserStrategy {
|
|||||||
TranslationNode targetNode = super.getOrCreateTargetNode(file, data);
|
TranslationNode targetNode = super.getOrCreateTargetNode(file, data);
|
||||||
|
|
||||||
try (Reader reader = new InputStreamReader(vf.getInputStream(), vf.getCharset())) {
|
try (Reader reader = new InputStreamReader(vf.getInputStream(), vf.getCharset())) {
|
||||||
Json5Element input = JSON5.parse(reader);
|
Json5Element input;
|
||||||
if(input != null && input.isJson5Object()) {
|
|
||||||
|
try {
|
||||||
|
input = JSON5.parse(reader);
|
||||||
|
if(input != null && !input.isJson5Object()) {
|
||||||
|
throw new SyntaxException("Expected a json5 object as root node", file);
|
||||||
|
}
|
||||||
|
} catch (Json5Exception ex) {
|
||||||
|
throw new SyntaxException(ex.getMessage(), file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(input != null) {
|
||||||
Json5Mapper.read(file.getLocale(), input.getAsJson5Object(), targetNode);
|
Json5Mapper.read(file.getLocale(), input.getAsJson5Object(), targetNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package de.marhali.easyi18n.io.parser.properties;
|
|||||||
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile;
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
|
|
||||||
|
import de.marhali.easyi18n.exception.SyntaxException;
|
||||||
import de.marhali.easyi18n.io.parser.ParserStrategy;
|
import de.marhali.easyi18n.io.parser.ParserStrategy;
|
||||||
import de.marhali.easyi18n.model.TranslationData;
|
import de.marhali.easyi18n.model.TranslationData;
|
||||||
import de.marhali.easyi18n.model.TranslationFile;
|
import de.marhali.easyi18n.model.TranslationFile;
|
||||||
@ -11,6 +12,7 @@ import de.marhali.easyi18n.util.KeyPathConverter;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
@ -38,10 +40,18 @@ public class PropertiesParserStrategy extends ParserStrategy {
|
|||||||
|
|
||||||
try(Reader reader = new InputStreamReader(vf.getInputStream(), vf.getCharset())) {
|
try(Reader reader = new InputStreamReader(vf.getInputStream(), vf.getCharset())) {
|
||||||
SortableProperties input = new SortableProperties(this.settings.isSorting());
|
SortableProperties input = new SortableProperties(this.settings.isSorting());
|
||||||
|
|
||||||
|
try {
|
||||||
input.load(reader);
|
input.load(reader);
|
||||||
|
} catch(IOException ex) {
|
||||||
|
throw new SyntaxException(ex.getMessage(), file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!input.isEmpty()) {
|
||||||
PropertiesMapper.read(file.getLocale(), input, targetData, converter);
|
PropertiesMapper.read(file.getLocale(), input, targetData, converter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull String write(@NotNull TranslationData data, @NotNull TranslationFile file) throws Exception {
|
public @NotNull String write(@NotNull TranslationData data, @NotNull TranslationFile file) throws Exception {
|
||||||
|
@ -2,6 +2,7 @@ package de.marhali.easyi18n.io.parser.yaml;
|
|||||||
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile;
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
|
|
||||||
|
import de.marhali.easyi18n.exception.SyntaxException;
|
||||||
import de.marhali.easyi18n.io.parser.ParserStrategy;
|
import de.marhali.easyi18n.io.parser.ParserStrategy;
|
||||||
import de.marhali.easyi18n.model.TranslationData;
|
import de.marhali.easyi18n.model.TranslationData;
|
||||||
import de.marhali.easyi18n.model.TranslationFile;
|
import de.marhali.easyi18n.model.TranslationFile;
|
||||||
@ -10,6 +11,7 @@ import de.marhali.easyi18n.settings.ProjectSettings;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import org.yaml.snakeyaml.error.YAMLException;
|
||||||
import thito.nodeflow.config.MapSection;
|
import thito.nodeflow.config.MapSection;
|
||||||
import thito.nodeflow.config.Section;
|
import thito.nodeflow.config.Section;
|
||||||
|
|
||||||
@ -34,7 +36,14 @@ public class YamlParserStrategy extends ParserStrategy {
|
|||||||
TranslationNode targetNode = super.getOrCreateTargetNode(file, data);
|
TranslationNode targetNode = super.getOrCreateTargetNode(file, data);
|
||||||
|
|
||||||
try(Reader reader = new InputStreamReader(vf.getInputStream(), vf.getCharset())) {
|
try(Reader reader = new InputStreamReader(vf.getInputStream(), vf.getCharset())) {
|
||||||
Section input = Section.parseToMap(reader);
|
Section input;
|
||||||
|
|
||||||
|
try {
|
||||||
|
input = Section.parseToMap(reader);
|
||||||
|
} catch (YAMLException ex) {
|
||||||
|
throw new SyntaxException(ex.getMessage(), file);
|
||||||
|
}
|
||||||
|
|
||||||
YamlMapper.read(file.getLocale(), input, targetNode);
|
YamlMapper.read(file.getLocale(), input, targetNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,9 @@ package de.marhali.easyi18n.util;
|
|||||||
import com.intellij.notification.*;
|
import com.intellij.notification.*;
|
||||||
import com.intellij.openapi.diagnostic.Logger;
|
import com.intellij.openapi.diagnostic.Logger;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
|
import de.marhali.easyi18n.action.OpenFileAction;
|
||||||
import de.marhali.easyi18n.action.SettingsAction;
|
import de.marhali.easyi18n.action.SettingsAction;
|
||||||
|
import de.marhali.easyi18n.exception.SyntaxException;
|
||||||
import de.marhali.easyi18n.io.IOHandler;
|
import de.marhali.easyi18n.io.IOHandler;
|
||||||
import de.marhali.easyi18n.settings.ProjectSettings;
|
import de.marhali.easyi18n.settings.ProjectSettings;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -16,6 +18,7 @@ import java.util.ResourceBundle;
|
|||||||
* @author marhali
|
* @author marhali
|
||||||
*/
|
*/
|
||||||
public class NotificationHelper {
|
public class NotificationHelper {
|
||||||
|
private static final String NOTIFICATION_GROUP = "Easy I18n Notification Group";
|
||||||
|
|
||||||
public static void createIOError(@NotNull ProjectSettings state, Exception ex) {
|
public static void createIOError(@NotNull ProjectSettings state, Exception ex) {
|
||||||
ResourceBundle bundle = ResourceBundle.getBundle("messages");
|
ResourceBundle bundle = ResourceBundle.getBundle("messages");
|
||||||
@ -26,11 +29,27 @@ public class NotificationHelper {
|
|||||||
Logger.getInstance(IOHandler.class).error(message, ex);
|
Logger.getInstance(IOHandler.class).error(message, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void createBadSyntaxNotification(Project project, SyntaxException ex) {
|
||||||
|
ResourceBundle bundle = ResourceBundle.getBundle("messages");
|
||||||
|
|
||||||
|
Notification notification = new Notification(
|
||||||
|
NOTIFICATION_GROUP,
|
||||||
|
bundle.getString("warning.bad-syntax"),
|
||||||
|
ex.getMessage(),
|
||||||
|
NotificationType.ERROR
|
||||||
|
);
|
||||||
|
|
||||||
|
notification.addAction(new OpenFileAction(ex.getFile().getVirtualFile(), false));
|
||||||
|
notification.addAction(new SettingsAction(false));
|
||||||
|
|
||||||
|
Notifications.Bus.notify(notification, project);
|
||||||
|
}
|
||||||
|
|
||||||
public static void createEmptyLocalesDirNotification(Project project) {
|
public static void createEmptyLocalesDirNotification(Project project) {
|
||||||
ResourceBundle bundle = ResourceBundle.getBundle("messages");
|
ResourceBundle bundle = ResourceBundle.getBundle("messages");
|
||||||
|
|
||||||
Notification notification = new Notification(
|
Notification notification = new Notification(
|
||||||
"Easy I18n Notification Group",
|
NOTIFICATION_GROUP,
|
||||||
"Easy I18n",
|
"Easy I18n",
|
||||||
bundle.getString("warning.missing-config"),
|
bundle.getString("warning.missing-config"),
|
||||||
NotificationType.WARNING);
|
NotificationType.WARNING);
|
||||||
|
@ -13,6 +13,7 @@ action.settings=Settings
|
|||||||
action.search=Search...
|
action.search=Search...
|
||||||
action.delete=Delete
|
action.delete=Delete
|
||||||
action.extract=Extract translation
|
action.extract=Extract translation
|
||||||
|
action.file=Open file
|
||||||
translation.key=Key
|
translation.key=Key
|
||||||
translation.locales=Locales
|
translation.locales=Locales
|
||||||
# Settings
|
# Settings
|
||||||
@ -65,3 +66,4 @@ error.io=An error occurred while processing translation files. \n\
|
|||||||
Please check examples at https://github.com/marhali/easy-i18n before reporting an issue!
|
Please check examples at https://github.com/marhali/easy-i18n before reporting an issue!
|
||||||
error.submit=Open Issue
|
error.submit=Open Issue
|
||||||
warning.missing-config=Configure your local project structure
|
warning.missing-config=Configure your local project structure
|
||||||
|
warning.bad-syntax=Syntax error in translation file
|
Loading…
x
Reference in New Issue
Block a user