Add menu to search for missing text keys
diff --git a/org.eclipse.scout.sdk.s2e.nls/plugin.xml b/org.eclipse.scout.sdk.s2e.nls/plugin.xml
index a57e6a4..9527783 100644
--- a/org.eclipse.scout.sdk.s2e.nls/plugin.xml
+++ b/org.eclipse.scout.sdk.s2e.nls/plugin.xml
@@ -52,4 +52,30 @@
</partition>
</javaCompletionProposalComputer>
</extension>
+ <extension point="org.eclipse.ui.menus">
+ <menuContribution locationURI="menu:org.eclipse.scout.sdk.s2e.ui.menu?after=org.eclipse.scout.sdk.s2e.ui.menu.missingClassIdSelected">
+ <separator
+ name="org.eclipse.scout.sdk.s2e.nls.menu.separator01"
+ visible="true">
+ </separator>
+ <command
+ commandId="org.eclipse.scout.sdk.s2e.nls.commands.searchMissingTextKeys"
+ id="org.eclipse.scout.sdk.s2e.nls.menu.searchMissingTextKeys"
+ style="push">
+ </command>
+ </menuContribution>
+ </extension>
+ <extension point="org.eclipse.ui.commands">
+ <command
+ name="Search missing text keys..."
+ id="org.eclipse.scout.sdk.s2e.nls.commands.searchMissingTextKeys"
+ categoryId="org.eclipse.scout.sdk.s2e.ui.commands.category">
+ </command>
+ </extension>
+ <extension point="org.eclipse.ui.handlers">
+ <handler
+ commandId="org.eclipse.scout.sdk.s2e.nls.commands.searchMissingTextKeys"
+ class="org.eclipse.scout.sdk.s2e.nls.internal.ui.handler.NlsFindMissingKeysHandler">
+ </handler>
+ </extension>
</plugin>
diff --git a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/model/NlsWorkspace.java b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/model/NlsWorkspace.java
index bce9577..33da8a2 100644
--- a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/model/NlsWorkspace.java
+++ b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/model/NlsWorkspace.java
@@ -10,12 +10,15 @@
******************************************************************************/
package org.eclipse.scout.sdk.s2e.nls.internal.model;
+import java.util.ArrayList;
+import java.util.Collection;
+
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
-import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
+import org.eclipse.scout.sdk.core.util.SdkLog;
import org.eclipse.scout.sdk.s2e.nls.NlsCore;
import org.eclipse.scout.sdk.s2e.nls.model.INlsProjectProvider;
import org.eclipse.scout.sdk.s2e.nls.model.INlsWorkspace;
@@ -26,24 +29,50 @@
*/
public final class NlsWorkspace implements INlsWorkspace {
- @Override
- public INlsProject getNlsProject(final Object[] args) throws CoreException {
- IExtensionRegistry reg = Platform.getExtensionRegistry();
- IExtensionPoint xp = reg.getExtensionPoint(NlsCore.PLUGIN_ID, "nlsProvider");
- IExtension[] extensions = xp.getExtensions();
- for (IExtension extension : extensions) {
- IConfigurationElement[] elements = extension.getConfigurationElements();
- for (IConfigurationElement element : elements) {
- if ("provider".equals(element.getName())) {
- INlsProjectProvider p = (INlsProjectProvider) element.createExecutableExtension("class");
- if (p != null) {
- INlsProject proj = p.getProject(args);
- if (proj != null) {
- return proj;
+ private volatile Collection<INlsProjectProvider> m_providers;
+
+ private Collection<INlsProjectProvider> getProviders() {
+ Collection<INlsProjectProvider> providers = m_providers;
+ if (providers != null) {
+ return providers;
+ }
+
+ synchronized (this) {
+ providers = m_providers;
+ if (providers != null) {
+ return providers;
+ }
+
+ providers = new ArrayList<>(2);
+ final IExtensionPoint xp = Platform.getExtensionRegistry().getExtensionPoint(NlsCore.PLUGIN_ID, "nlsProvider");
+ for (final IExtension extension : xp.getExtensions()) {
+ final IConfigurationElement[] elements = extension.getConfigurationElements();
+ for (final IConfigurationElement element : elements) {
+ if ("provider".equals(element.getName())) {
+ try {
+ final INlsProjectProvider p = (INlsProjectProvider) element.createExecutableExtension("class");
+ if (p != null) {
+ providers.add(p);
+ }
+ }
+ catch (final CoreException e) {
+ SdkLog.error("Unable to create extension '{}'.", element.getNamespaceIdentifier(), e);
}
}
}
}
+ m_providers = providers;
+ return providers;
+ }
+ }
+
+ @Override
+ public INlsProject getNlsProject(final Object... args) {
+ for (final INlsProjectProvider p : getProviders()) {
+ final INlsProject proj = p.getProject(args);
+ if (proj != null) {
+ return proj;
+ }
}
return null;
}
diff --git a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/search/JavaProjectsWalker.java b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/search/JavaProjectsWalker.java
new file mode 100644
index 0000000..1654011
--- /dev/null
+++ b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/search/JavaProjectsWalker.java
@@ -0,0 +1,282 @@
+/*******************************************************************************
+ * Copyright (c) 2017 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.scout.sdk.s2e.nls.internal.search;
+
+import static java.util.Collections.unmodifiableCollection;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Optional;
+import java.util.function.BiPredicate;
+import java.util.function.Consumer;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.Validate;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.scout.sdk.core.util.SdkException;
+
+/**
+ * <h3>{@link JavaProjectsWalker}</h3>
+ *
+ * @since 7.0.100
+ */
+public class JavaProjectsWalker {
+
+ private final String m_taskName;
+ private final Collection<String> m_fileExtensions;
+
+ private boolean m_skipOutputLocation;
+ private boolean m_skipHiddenPaths;
+ private BiPredicate<Path, BasicFileAttributes> m_fileFilter;
+
+ public JavaProjectsWalker(final String taskName) {
+ m_taskName = Validate.notNull(taskName);
+ m_fileExtensions = new ArrayList<>();
+ m_skipOutputLocation = true;
+ m_skipHiddenPaths = true;
+ }
+
+ public void walk(final Consumer<WorkspaceFile> visitor, final IProgressMonitor monitor) throws CoreException {
+ final IJavaProject[] javaProjects = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot()).getJavaProjects();
+ monitor.beginTask(taskName(), javaProjects.length);
+ for (final IJavaProject root : javaProjects) {
+ final IProject p = root.getProject();
+ final Path outputLocation;
+ if (isSkipOutputLocation()) {
+ outputLocation = new File(p.getLocation().toOSString(), root.getOutputLocation().removeFirstSegments(1).toOSString()).toPath();
+ }
+ else {
+ outputLocation = null;
+ }
+
+ searchInFolder(visitor, p.getLocation().toFile().toPath(), Charset.forName(p.getDefaultCharset()), outputLocation, monitor);
+
+ if (monitor.isCanceled()) {
+ return;
+ }
+ monitor.worked(1);
+ }
+ }
+
+ protected void searchInFolder(final Consumer<WorkspaceFile> visitor, final Path folder, final Charset charset, final Path outputFolder, final IProgressMonitor monitor) {
+ try {
+ Files.walkFileTree(folder,
+ new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) {
+ if (monitor.isCanceled()) {
+ return FileVisitResult.TERMINATE;
+ }
+ if (dir.equals(outputFolder)) {
+ return FileVisitResult.SKIP_SUBTREE;
+ }
+ if (!hiddenFilterAndCustomFilterAccepted(dir, attrs)) {
+ return FileVisitResult.SKIP_SUBTREE;
+ }
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) {
+ if (monitor.isCanceled()) {
+ return FileVisitResult.TERMINATE;
+ }
+ if (allFiltersAccepted(file, attrs)) {
+ visitor.accept(new WorkspaceFile(file, charset));
+ }
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ }
+ catch (final IOException e) {
+ throw new SdkException(e);
+ }
+ }
+
+ protected boolean hiddenFilterAndCustomFilterAccepted(final Path file, final BasicFileAttributes attrs) {
+ if (isSkipHiddenPaths() && isHidden(file)) {
+ return false;
+ }
+
+ return fileFilter()
+ .map(filter -> filter.test(file, attrs))
+ .orElse(Boolean.TRUE)
+ .booleanValue();
+ }
+
+ protected boolean allFiltersAccepted(final Path file, final BasicFileAttributes attrs) {
+ if (!acceptFileExtension(file)) {
+ return false;
+ }
+ return hiddenFilterAndCustomFilterAccepted(file, attrs);
+ }
+
+ protected boolean acceptFileExtension(final Path file) {
+ final Path path = file.getFileName();
+ if (path == null) {
+ return false;
+ }
+ final String fileName = path.toString().toLowerCase();
+ for (final String extension : extensionsAccepted()) {
+ if (fileName.endsWith(extension)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected static boolean isHidden(final Path path) {
+ final Path fileName = path.getFileName();
+ return fileName != null && fileName.toString().startsWith(".");
+ }
+
+ public String taskName() {
+ return m_taskName;
+ }
+
+ public boolean isSkipOutputLocation() {
+ return m_skipOutputLocation;
+ }
+
+ public JavaProjectsWalker withSkipOutputLocation(final boolean skipOutputLocation) {
+ m_skipOutputLocation = skipOutputLocation;
+ return this;
+ }
+
+ public boolean isSkipHiddenPaths() {
+ return m_skipHiddenPaths;
+ }
+
+ public JavaProjectsWalker withSkipHiddenPaths(final boolean skipHiddenPaths) {
+ m_skipHiddenPaths = skipHiddenPaths;
+ return this;
+ }
+
+ public Optional<BiPredicate<Path, BasicFileAttributes>> fileFilter() {
+ return Optional.ofNullable(m_fileFilter);
+ }
+
+ public JavaProjectsWalker withFilter(final BiPredicate<Path, BasicFileAttributes> fileFilter) {
+ m_fileFilter = fileFilter;
+ return this;
+ }
+
+ public Collection<String> extensionsAccepted() {
+ return unmodifiableCollection(m_fileExtensions);
+ }
+
+ public JavaProjectsWalker withExtensionsAccepted(final String... extensions) {
+ final Collection<String> l = extensions == null ? null : Arrays.asList(extensions);
+ return withExtensionsAccepted(l);
+ }
+
+ public JavaProjectsWalker withExtensionsAccepted(final Collection<String> extensions) {
+ m_fileExtensions.clear();
+ if (extensions != null && !extensions.isEmpty()) {
+ for (final String e : extensions) {
+ if (StringUtils.isNotBlank(e)) {
+ m_fileExtensions.add(e);
+ }
+ }
+ }
+ return this;
+ }
+
+ public static class WorkspaceFile {
+ private final Path m_file;
+ private final Charset m_charset;
+ private char[] m_content; // loaded on request
+ private Optional<IFile> m_workspaceFile; // loaded on request
+
+ protected WorkspaceFile(final Path file, final Charset charset) {
+ m_file = Validate.notNull(file);
+ m_charset = Validate.notNull(charset);
+ }
+
+ public Charset charset() {
+ return m_charset;
+ }
+
+ public Path path() {
+ return m_file;
+ }
+
+ public Optional<IFile> inWorkspace() {
+ if (m_workspaceFile == null) {
+ m_workspaceFile = Optional.ofNullable(resolveInWorkspace(path()));
+ }
+ return m_workspaceFile;
+ }
+
+ protected static IFile resolveInWorkspace(final Path file) {
+ final IFile[] workspaceFiles = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(file.toUri());
+ if (workspaceFiles.length < 1) {
+ return null;
+ }
+ final IFile workspaceFile = workspaceFiles[0];
+ if (!workspaceFile.exists()) {
+ return null;
+ }
+ return workspaceFile;
+ }
+
+ public char[] content() {
+ if (m_content == null) {
+ try {
+ m_content = charset().decode(ByteBuffer.wrap(Files.readAllBytes(path()))).array();
+ }
+ catch (final IOException e) {
+ throw new SdkException("Unable to read content of file '" + path() + "'.", e);
+ }
+ }
+ return m_content;
+ }
+
+ @Override
+ public String toString() {
+ return WorkspaceFile.class.getSimpleName() + ": " + path();
+ }
+
+ @Override
+ public int hashCode() {
+ return m_file.hashCode();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ final WorkspaceFile other = (WorkspaceFile) obj;
+ return m_file.equals(other.m_file);
+ }
+ }
+}
diff --git a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/search/NlsKeySearchQuery.java b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/search/NlsFindKeyQuery.java
similarity index 94%
rename from org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/search/NlsKeySearchQuery.java
rename to org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/search/NlsFindKeyQuery.java
index b228d65..f90b603 100644
--- a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/search/NlsKeySearchQuery.java
+++ b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/search/NlsFindKeyQuery.java
@@ -23,12 +23,12 @@
/**
* <h4>NlsKeySearchQuery</h4>
*/
-public class NlsKeySearchQuery extends FileSearchQuery {
+public class NlsFindKeyQuery extends FileSearchQuery {
private final String m_nlsKey;
private final INlsProject m_project;
- public NlsKeySearchQuery(INlsProject project, String nlsKey) {
+ public NlsFindKeyQuery(INlsProject project, String nlsKey) {
super("", false, false, null);
m_project = project;
m_nlsKey = nlsKey;
@@ -46,7 +46,6 @@
@Override
public FileSearchResult getSearchResult() {
-
return (FileSearchResult) super.getSearchResult();
}
diff --git a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/search/NlsFindKeysJob.java b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/search/NlsFindKeysJob.java
index f68a61b..d2d6718 100644
--- a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/search/NlsFindKeysJob.java
+++ b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/search/NlsFindKeysJob.java
@@ -10,31 +10,24 @@
******************************************************************************/
package org.eclipse.scout.sdk.s2e.nls.internal.search;
-import java.io.IOException;
-import java.nio.file.FileVisitResult;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.SimpleFileVisitor;
-import java.nio.file.attribute.BasicFileAttributes;
+import static java.util.Collections.singletonList;
+
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
import org.eclipse.scout.sdk.s2e.job.AbstractJob;
+import org.eclipse.scout.sdk.s2e.nls.internal.search.JavaProjectsWalker.WorkspaceFile;
import org.eclipse.scout.sdk.s2e.nls.model.INlsEntry;
import org.eclipse.scout.sdk.s2e.nls.project.INlsProject;
-import org.eclipse.scout.sdk.s2e.util.ScoutStatus;
import org.eclipse.search.ui.text.Match;
/**
@@ -42,28 +35,28 @@
*/
public class NlsFindKeysJob extends AbstractJob {
- private final List<String> m_searchKeys;
+ private final List<char[]> m_searchKeys;
private final Map<String, List<Match>> m_matches;
- public NlsFindKeysJob(String nlsKey, String jobTitle) {
- this(Collections.singletonList(nlsKey), jobTitle);
+ public NlsFindKeysJob(final String nlsKey, final String jobTitle) {
+ this(singletonList(nlsKey), jobTitle);
}
- public NlsFindKeysJob(INlsProject project, String jobTitle) {
+ public NlsFindKeysJob(final INlsProject project, final String jobTitle) {
this(getLocalKeys(project), jobTitle);
}
- protected NlsFindKeysJob(List<String> searchKeys, String jobTitle) {
+ protected NlsFindKeysJob(final Collection<String> searchKeys, final String jobTitle) {
super(jobTitle);
m_searchKeys = new ArrayList<>(searchKeys.size() * 2);
- for (String key : searchKeys) {
- m_searchKeys.add("\"" + key + "\"");
- m_searchKeys.add('\'' + key + '\''); // e.g. for search in .js files
+ for (final String key : searchKeys) {
+ m_searchKeys.add(('"' + key + '"').toCharArray());
+ m_searchKeys.add(('\'' + key + '\'').toCharArray()); // e.g. for search in .js files
}
m_matches = new HashMap<>();
}
- protected static List<String> getLocalKeys(INlsProject project) {
+ private static List<String> getLocalKeys(final INlsProject project) {
return project.getAllEntries().stream()
.filter(entry -> entry.getType() == INlsEntry.TYPE_LOCAL)
.map(INlsEntry::getKey)
@@ -71,114 +64,36 @@
}
@Override
- public void execute(IProgressMonitor monitor) throws CoreException {
+ public void execute(final IProgressMonitor monitor) throws CoreException {
m_matches.clear();
- IJavaProject[] javaProjects = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot()).getJavaProjects();
- monitor.beginTask("Searching for NLS keys", javaProjects.length);
- for (IJavaProject root : javaProjects) {
- monitor.setTaskName("Searching in '" + root.getElementName() + "'.");
-
- IProject p = root.getProject();
- Path outputLocation = new java.io.File(p.getLocation().toOSString(), root.getOutputLocation().removeFirstSegments(1).toOSString()).toPath();
- searchInFolder(p.getLocation().toFile().toPath(), p.getDefaultCharset(), outputLocation, monitor);
-
- if (monitor.isCanceled()) {
- return;
- }
- monitor.worked(1);
- }
+ new JavaProjectsWalker(getName())
+ .withExtensionsAccepted(SuffixConstants.EXTENSION_java, "js", "html", "less", "json", "xml", "sql", "css", "svg", "txt", "jsp")
+ .walk(this::searchInFile, monitor);
}
- protected void searchInFolder(Path folder, final String charset, final Path outputFolder, final IProgressMonitor monitor) throws CoreException {
- try {
- Files.walkFileTree(folder,
- new SimpleFileVisitor<Path>() {
- @Override
- public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
- if (monitor.isCanceled()) {
- return FileVisitResult.TERMINATE;
- }
- if (dir.equals(outputFolder)) {
- return FileVisitResult.SKIP_SUBTREE;
- }
- Path fileName = dir.getFileName();
- boolean isHiddenDir = fileName != null && fileName.toString().startsWith(".");
- if (isHiddenDir) {
- return FileVisitResult.SKIP_SUBTREE;
- }
- return FileVisitResult.CONTINUE;
- }
-
- @Override
- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
- if (isInterestingFile(file, attrs)) {
- searchInFile(file, charset, monitor);
- }
- if (monitor.isCanceled()) {
- return FileVisitResult.TERMINATE;
- }
- return FileVisitResult.CONTINUE;
- }
- });
- }
- catch (IOException e) {
- throw new CoreException(new ScoutStatus(e));
- }
- }
-
- protected boolean isInterestingFile(Path file, BasicFileAttributes attrs) {
- if (!attrs.isRegularFile()) {
- return false;
- }
- Path path = file.getFileName();
- if (path == null) {
- return false;
- }
- String fileName = path.toString().toLowerCase();
- String[] interestingFileExtensions = {SuffixConstants.SUFFIX_STRING_java, ".js", ".html", ".less", ".json", ".xml", ".sql", ".css", ".svg", ".txt", ".jsp"};
- for (String extension : interestingFileExtensions) {
- if (fileName.endsWith(extension)) {
- return true;
- }
- }
- return false;
- }
-
- protected void searchInFile(Path file, String charset, IProgressMonitor monitor) throws IOException {
- IFile[] workspaceFiles = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(file.toUri());
- if (workspaceFiles.length < 1) {
- return;
- }
- IFile workspaceFile = workspaceFiles[0];
- if (!workspaceFile.exists()) {
- return;
- }
-
- String content = new String(Files.readAllBytes(file), charset);
- for (String search : m_searchKeys) {
+ protected void searchInFile(final WorkspaceFile file) {
+ for (final char[] search : m_searchKeys) {
int pos = 0;
- int index = -1;
- while ((index = content.indexOf(search, pos)) >= 0) {
- if (monitor.isCanceled()) {
- return;
+ int index;
+ while ((index = CharOperation.indexOf(search, file.content(), true, pos)) >= 0) {
+ if (file.inWorkspace().isPresent()) {
+ final Match match = new Match(file.inWorkspace().get(), index, search.length);
+ final String key = String.valueOf(search, 1, search.length - 2); // remove starting and ending quotes
+ acceptNlsKeyMatch(key, match);
}
-
- Match match = new Match(workspaceFile, index, search.length());
- String key = search.substring(1, search.length() - 1); // remove starting and ending quotes
- acceptNlsKeyMatch(key, match);
- pos = index + search.length();
+ pos = index + search.length;
}
}
}
- protected void acceptNlsKeyMatch(String nlsKey, Match match) {
+ protected void acceptNlsKeyMatch(final String nlsKey, final Match match) {
m_matches
.computeIfAbsent(nlsKey, key -> new ArrayList<>())
.add(match);
}
- public List<Match> getMatches(String nlsKey) {
- List<Match> list = m_matches.get(nlsKey);
+ public List<Match> getMatches(final String nlsKey) {
+ final List<Match> list = m_matches.get(nlsKey);
if (list == null) {
return Collections.emptyList();
}
diff --git a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/search/NlsFindMissingKeysJob.java b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/search/NlsFindMissingKeysJob.java
new file mode 100644
index 0000000..c97345a
--- /dev/null
+++ b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/search/NlsFindMissingKeysJob.java
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ * Copyright (c) 2017 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.scout.sdk.s2e.nls.internal.search;
+
+import static java.util.Collections.emptySet;
+import static java.util.Collections.unmodifiableList;
+
+import java.nio.CharBuffer;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.MatchResult;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.scout.sdk.core.s.IScoutRuntimeTypes;
+import org.eclipse.scout.sdk.core.util.SdkException;
+import org.eclipse.scout.sdk.core.util.SdkLog;
+import org.eclipse.scout.sdk.s2e.job.AbstractJob;
+import org.eclipse.scout.sdk.s2e.nls.NlsCore;
+import org.eclipse.scout.sdk.s2e.nls.internal.search.JavaProjectsWalker.WorkspaceFile;
+import org.eclipse.scout.sdk.s2e.nls.internal.ui.formatter.InputValidator;
+import org.eclipse.scout.sdk.s2e.nls.project.INlsProject;
+import org.eclipse.scout.sdk.s2e.util.S2eUtils;
+import org.eclipse.search.ui.text.Match;
+
+/**
+ * <h3>{@link NlsFindMissingKeysJob}</h3>
+ * <p>
+ * Searches for NLS keys that are used in the code but do not exist.
+ *
+ * @since 7.0.100
+ */
+public class NlsFindMissingKeysJob extends AbstractJob {
+
+ private final Map<String, Collection<Pattern>> m_patternsByFileType;
+ private final Map<IJavaProject, Set<String>> m_existingKeys;
+ private final List<Match> m_matches;
+ private final List<Match> m_errorMatches;
+ private final String m_textClassName;
+
+ public NlsFindMissingKeysJob() {
+ super("Search for text keys that are used but do not exist.");
+ m_existingKeys = new HashMap<>();
+ m_matches = new ArrayList<>();
+ m_errorMatches = new ArrayList<>();
+ m_patternsByFileType = new HashMap<>();
+
+ final String nlsKeyPattern = InputValidator.REGEX_NLS_KEY_NAME.pattern();
+ final Pattern jsonTextKeyPat = Pattern.compile("\\$\\{textKey:(" + nlsKeyPattern + ')');
+ final Pattern jsTextKeyPat = Pattern.compile("session\\.text\\(('?)(" + nlsKeyPattern + ")('?)");
+ m_patternsByFileType.put(SuffixConstants.EXTENSION_java, Collections.singletonList(Pattern.compile("TEXTS\\.get\\((\"?)(" + nlsKeyPattern + ")(\"?)")));
+ m_patternsByFileType.put("json", Collections.singletonList(jsonTextKeyPat));
+ m_patternsByFileType.put("js", Arrays.asList(jsTextKeyPat, jsonTextKeyPat));
+ m_patternsByFileType.put("html", Arrays.asList(Pattern.compile("\\<scout:message key=\"(" + nlsKeyPattern + ")\"\\s*/?\\>"), jsTextKeyPat, jsonTextKeyPat));
+
+ m_textClassName = Signature.getSimpleName(IScoutRuntimeTypes.TEXTS) + SuffixConstants.SUFFIX_STRING_java;
+ }
+
+ private static Set<String> keysVisibleFrom(final IJavaProject jp) {
+ if (!S2eUtils.exists(jp)) {
+ return emptySet();
+ }
+
+ final INlsProject nlsProject = NlsCore.getNlsWorkspace().getNlsProject(jp);
+ if (nlsProject == null) {
+ return emptySet();
+ }
+ return nlsProject.getAllKeys();
+ }
+
+ @Override
+ protected void execute(final IProgressMonitor monitor) throws CoreException {
+ m_matches.clear();
+ m_errorMatches.clear();
+ new JavaProjectsWalker(getName())
+ .withExtensionsAccepted(m_patternsByFileType.keySet())
+ .withFilter(this::isInterestingPath)
+ .walk(this::searchInFile, monitor);
+ }
+
+ protected boolean isInterestingPath(final Path p, final BasicFileAttributes attrs) {
+ if (attrs.isDirectory()) {
+ // skip tests && archetype resources
+ return !p.endsWith("src/test") && !p.endsWith("archetype-resources") && !p.endsWith("generated-resources");
+ }
+ return !p.endsWith(m_textClassName);
+ }
+
+ protected void searchInFile(final WorkspaceFile file) {
+ if (!file.inWorkspace().isPresent()) {
+ SdkLog.warning("File '{}' could not be found in the current Eclipse Workspace.", file.path());
+ return;
+ }
+
+ final String fileName = file.path().getFileName().toString().toLowerCase();
+ final int lastDotPos = fileName.lastIndexOf('.');
+ final String extension = fileName.substring(lastDotPos + 1);
+ final Collection<Pattern> patterns = m_patternsByFileType.get(extension);
+ if (patterns == null || patterns.isEmpty()) {
+ throw new SdkException("Unexpected: no pattern for file: " + file.path());
+ }
+
+ for (final Pattern p : patterns) {
+ final Matcher matcher = p.matcher(CharBuffer.wrap(file.content()));
+ while (matcher.find()) {
+ final int keyGroup;
+ if (matcher.groupCount() > 1) {
+ // pattern with optional literal delimiter: '"' for java, ''' for js
+ // check if the literal delimiter is present. if not present: not possible to detect the real key -> add to error list.
+ keyGroup = 2;
+ final boolean noLiteral = StringUtils.isEmpty(matcher.group(1)) || StringUtils.isEmpty(matcher.group(3));
+ if (noLiteral) {
+ registerMatch(file, matcher, m_errorMatches, keyGroup);
+ continue;
+ }
+ }
+ else {
+ // pattern without literal delimiter
+ keyGroup = 1;
+ }
+
+ final String key = matcher.group(keyGroup);
+ if (!keyExists(file.inWorkspace().get().getProject(), key)) {
+ registerMatch(file, matcher, m_matches, keyGroup);
+ }
+ }
+ }
+ }
+
+ protected boolean keyExists(final IProject context, final String key) {
+ return m_existingKeys
+ .computeIfAbsent(JavaCore.create(context), NlsFindMissingKeysJob::keysVisibleFrom)
+ .contains(key);
+ }
+
+ protected static Match registerMatch(final WorkspaceFile file, final MatchResult matcher, final Collection<Match> targetList, final int keyGroup) {
+ final int index = matcher.start(keyGroup);
+ final Match match = new Match(file.inWorkspace().get(), index, matcher.end(keyGroup) - index);
+ targetList.add(match);
+ return match;
+ }
+
+ public List<Match> matches() {
+ return unmodifiableList(m_matches);
+ }
+
+ public List<Match> errors() {
+ return unmodifiableList(m_errorMatches);
+ }
+}
diff --git a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/search/NlsFindMissingKeysQuery.java b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/search/NlsFindMissingKeysQuery.java
new file mode 100644
index 0000000..a0ba13e
--- /dev/null
+++ b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/search/NlsFindMissingKeysQuery.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2017 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.scout.sdk.s2e.nls.internal.search;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.search.internal.ui.text.FileSearchQuery;
+import org.eclipse.search.internal.ui.text.FileSearchResult;
+import org.eclipse.search.ui.text.Match;
+
+/**
+ * <h3>{@link NlsFindMissingKeysQuery}</h3>
+ *
+ * @since 7.0.100
+ */
+public class NlsFindMissingKeysQuery extends FileSearchQuery {
+
+ public NlsFindMissingKeysQuery() {
+ super("", false, false, null);
+ }
+
+ @Override
+ public String getResultLabel(final int matches) {
+ return "References to missing text keys (" + matches + ").";
+ }
+
+ @Override
+ public String getLabel() {
+ return "Find references to missing text keys...";
+ }
+
+ @Override
+ public FileSearchResult getSearchResult() {
+ return (FileSearchResult) super.getSearchResult();
+ }
+
+ @Override
+ public IStatus run(final IProgressMonitor monitor) {
+ final NlsFindMissingKeysJob nlsFindMissingKeysJob = new NlsFindMissingKeysJob();
+ final IStatus result = nlsFindMissingKeysJob.run(monitor);
+ if (result != null && result.getSeverity() == IStatus.CANCEL) {
+ return result;
+ }
+
+ final List<Match> missingKeys = nlsFindMissingKeysJob.matches();
+ final List<Match> unableToDetect = nlsFindMissingKeysJob.errors();
+ final FileSearchResult searchResult = getSearchResult();
+ searchResult.removeAll();
+ searchResult.addMatches(missingKeys.toArray(new Match[missingKeys.size()]));
+ searchResult.addMatches(unableToDetect.toArray(new Match[unableToDetect.size()]));
+
+ return Status.OK_STATUS;
+ }
+}
diff --git a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/serviceproject/ServiceNlsProjectProvider.java b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/serviceproject/ServiceNlsProjectProvider.java
index 0cd4790..fcd3350 100644
--- a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/serviceproject/ServiceNlsProjectProvider.java
+++ b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/serviceproject/ServiceNlsProjectProvider.java
@@ -237,6 +237,10 @@
// text service file
return getProjectByTextServiceFile((IFile) args[0]);
}
+ else if (args[0] instanceof IJavaProject) {
+ // java project
+ return getProjectByJavaProject((IJavaProject) args[0]);
+ }
}
else if (args.length == 2 && args[0] instanceof IType) {
if (args[1] instanceof IJavaProject || args[1] == null) {
@@ -263,14 +267,28 @@
}
}
+ private static INlsProject getProjectByJavaProject(final IJavaProject jp) {
+ if (!S2eUtils.exists(jp)) {
+ return null;
+ }
+ try {
+ final Set<IType> txtProviderServices = getRegisteredTextProviderTypes(jp);
+ return textProviderTypesToNlsProject(txtProviderServices);
+ }
+ catch (final CoreException e) {
+ SdkLog.warning("Could not load text provider services for java project: {}", jp.getElementName(), e);
+ }
+ return null;
+ }
+
private static INlsProject getProjectByTextServiceFile(IFile f) {
try {
IType type = getITypeForFile(f);
if (type != null) {
- return NlsCore.getNlsWorkspace().getNlsProject(new Object[]{type});
+ return NlsCore.getNlsWorkspace().getNlsProject(type);
}
}
- catch (CoreException e) {
+ catch (JavaModelException e) {
SdkLog.warning("Could not load text provider services for file: {}", f.getFullPath().toString(), e);
}
return null;
diff --git a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/simpleproject/SimpleNlsProject.java b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/simpleproject/SimpleNlsProject.java
index b1c57d0..0700531 100644
--- a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/simpleproject/SimpleNlsProject.java
+++ b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/simpleproject/SimpleNlsProject.java
@@ -176,12 +176,7 @@
private void setSuperType(IType superType) {
// find parent
if (superType != null) {
- try {
- setParent(NlsCore.getNlsWorkspace().getNlsProject(new Object[]{superType}));
- }
- catch (CoreException e) {
- SdkLog.error("parent of NLS project could not be found. Looked for type '{}'.", superType.getFullyQualifiedName(), e);
- }
+ setParent(NlsCore.getNlsWorkspace().getNlsProject(superType));
}
}
diff --git a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/simpleproject/SimpleNlsProjectProvider.java b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/simpleproject/SimpleNlsProjectProvider.java
index fc9da41..c75a5ae 100644
--- a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/simpleproject/SimpleNlsProjectProvider.java
+++ b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/simpleproject/SimpleNlsProjectProvider.java
@@ -14,10 +14,10 @@
import java.util.Map;
import org.eclipse.core.resources.IFile;
-import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.scout.sdk.core.util.SdkLog;
import org.eclipse.scout.sdk.s2e.nls.NlsCore;
import org.eclipse.scout.sdk.s2e.nls.model.INlsProjectProvider;
@@ -84,7 +84,7 @@
}
}
}
- catch (CoreException e) {
+ catch (JavaModelException e) {
SdkLog.warning("Could not load NlsFile: {}", f.getFullPath().toString(), e);
}
}
diff --git a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/ui/action/FindReferencesAction.java b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/ui/action/FindReferencesAction.java
index f289a14..2f62bd4 100644
--- a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/ui/action/FindReferencesAction.java
+++ b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/ui/action/FindReferencesAction.java
@@ -14,7 +14,7 @@
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.scout.sdk.s2e.nls.INlsIcons;
import org.eclipse.scout.sdk.s2e.nls.NlsCore;
-import org.eclipse.scout.sdk.s2e.nls.internal.search.NlsKeySearchQuery;
+import org.eclipse.scout.sdk.s2e.nls.internal.search.NlsFindKeyQuery;
import org.eclipse.scout.sdk.s2e.nls.project.INlsProject;
import org.eclipse.search.ui.NewSearchUI;
@@ -34,7 +34,7 @@
@Override
public void run() {
- NewSearchUI.runQueryInBackground(new NlsKeySearchQuery(getProject(), getKey()));
+ NewSearchUI.runQueryInBackground(new NlsFindKeyQuery(getProject(), getKey()));
}
@Override
diff --git a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/ui/editor/NlsEditor.java b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/ui/editor/NlsEditor.java
index 89cfd64..93d6696 100644
--- a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/ui/editor/NlsEditor.java
+++ b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/ui/editor/NlsEditor.java
@@ -71,27 +71,22 @@
private void createTablePage() {
INlsProject nlsProjects = null;
IEditorInput input = getEditorInput();
- try {
- if (input instanceof FileEditorInput) {
- nlsProjects = NlsCore.getNlsWorkspace().getNlsProject(new Object[]{((FileEditorInput) input).getFile()});
- }
- else if (input instanceof NlsTypeEditorInput) {
- nlsProjects = NlsCore.getNlsWorkspace().getNlsProject(new Object[]{((NlsTypeEditorInput) input).getType()});
- }
+ if (input instanceof FileEditorInput) {
+ nlsProjects = NlsCore.getNlsWorkspace().getNlsProject(new Object[]{((FileEditorInput) input).getFile()});
+ }
+ else if (input instanceof NlsTypeEditorInput) {
+ nlsProjects = NlsCore.getNlsWorkspace().getNlsProject(new Object[]{((NlsTypeEditorInput) input).getType()});
+ }
- if (nlsProjects != null) {
- setPartName(nlsProjects.getName());
- }
- else {
- setPartName("Translations");
- }
- NlsTablePage page = new NlsTablePage(getContainer(), nlsProjects);
- m_tablePageIndex = addPage(page);
- setPageText(m_tablePageIndex, "Translations");
+ if (nlsProjects != null) {
+ setPartName(nlsProjects.getName());
}
- catch (CoreException e) {
- SdkLog.error("could not load file: {}", input.getName(), e);
+ else {
+ setPartName("Translations");
}
+ NlsTablePage page = new NlsTablePage(getContainer(), nlsProjects);
+ m_tablePageIndex = addPage(page);
+ setPageText(m_tablePageIndex, "Translations");
}
@Override
diff --git a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/ui/formatter/InputValidator.java b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/ui/formatter/InputValidator.java
index 8574226..db7983e 100644
--- a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/ui/formatter/InputValidator.java
+++ b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/ui/formatter/InputValidator.java
@@ -22,7 +22,7 @@
import org.eclipse.swt.SWT;
public final class InputValidator {
- private static final Pattern REGEX_NLS_KEY_NAME = Pattern.compile("\\b[A-Za-z0-9][a-zA-Z0-9_.\\-]{0,200}\\b");
+ public static final Pattern REGEX_NLS_KEY_NAME = Pattern.compile("[A-Za-z][a-zA-Z0-9_.\\-]{0,200}");
private InputValidator() {
}
diff --git a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/ui/handler/NlsFindMissingKeysHandler.java b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/ui/handler/NlsFindMissingKeysHandler.java
new file mode 100644
index 0000000..24cf144
--- /dev/null
+++ b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/internal/ui/handler/NlsFindMissingKeysHandler.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2017 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.scout.sdk.s2e.nls.internal.ui.handler;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.scout.sdk.s2e.nls.internal.search.NlsFindMissingKeysQuery;
+import org.eclipse.search.ui.NewSearchUI;
+
+/**
+ * <h3>{@link NlsFindMissingKeysHandler}</h3>
+ *
+ * @since 7.0.100
+ */
+public class NlsFindMissingKeysHandler extends AbstractHandler {
+ @Override
+ public Object execute(final ExecutionEvent event) {
+ NewSearchUI.runQueryInBackground(new NlsFindMissingKeysQuery());
+ return null;
+ }
+}
diff --git a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/model/INlsWorkspace.java b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/model/INlsWorkspace.java
index 7ca238e..10dc9f9 100644
--- a/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/model/INlsWorkspace.java
+++ b/org.eclipse.scout.sdk.s2e.nls/src/main/java/org/eclipse/scout/sdk/s2e/nls/model/INlsWorkspace.java
@@ -10,7 +10,6 @@
******************************************************************************/
package org.eclipse.scout.sdk.s2e.nls.model;
-import org.eclipse.core.runtime.CoreException;
import org.eclipse.scout.sdk.s2e.nls.project.INlsProject;
/**
@@ -25,7 +24,6 @@
* @param args
* The arguments to be used when trying to find a INlsProject.
* @return the NlsProject hierarchy for the given parameters or null.
- * @throws CoreException
*/
- INlsProject getNlsProject(Object[] args) throws CoreException;
+ INlsProject getNlsProject(Object... args);
}