From 750769a996e859e45463e06319baf4780829a386 Mon Sep 17 00:00:00 2001 From: Mikhail Sokolov Date: Wed, 5 Sep 2018 20:16:13 +0300 Subject: [PATCH 1/4] =?UTF-8?q?IDEA-196737=20New=20SE:=20=E2=80=9CShow=20i?= =?UTF-8?q?n=20find=20window=E2=80=9D=20option=20shows=20only=20found=20it?= =?UTF-8?q?ems=20instead=20of=20all?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../searcheverywhere/SearchEverywhereUI.java | 68 ++++++++++++++----- 1 file changed, 51 insertions(+), 17 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereUI.java b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereUI.java index 8cb1562a45e4..2882ca1cade7 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereUI.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereUI.java @@ -14,14 +14,17 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ApplicationNamesInfo; +import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.keymap.KeymapUtil; +import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; import com.intellij.openapi.progress.util.ProgressIndicatorBase; import com.intellij.openapi.progress.util.ProgressWindow; +import com.intellij.openapi.progress.util.TooManyUsagesStatus; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.DumbService; @@ -44,6 +47,7 @@ import com.intellij.ui.components.fields.ExtendableTextField; import com.intellij.ui.popup.PopupUpdateProcessor; import com.intellij.usageView.UsageInfo; import com.intellij.usages.*; +import com.intellij.usages.impl.UsageViewManagerImpl; import com.intellij.util.Alarm; import com.intellij.util.text.MatcherHolder; import com.intellij.util.ui.DialogUtil; @@ -1047,7 +1051,7 @@ public class SearchEverywhereUI extends BorderLayoutPanel implements Disposable, Collection cached = contributors.stream() .flatMap(contributor -> myListModel.getFoundItems(contributor).stream()) - .collect(Collectors.toList()); + .collect(Collectors.toSet()); fillUsages(cached, usages, targets); Collection contributorsForAdditionalSearch; @@ -1062,14 +1066,44 @@ public class SearchEverywhereUI extends BorderLayoutPanel implements Disposable, @Override public void run(@NotNull ProgressIndicator indicator) { + progressIndicator.start(); + TooManyUsagesStatus tooManyUsagesStatus = TooManyUsagesStatus.createFor(progressIndicator); + + Collection foundElements = new ArrayList<>(); + int alreadyFoundCount = cached.size(); contributorsForAdditionalSearch.forEach(contributor -> { if (!progressIndicator.isCanceled()) { - //todo overflow #UX-1 - List foundElements = - contributor.search(searchText, everywhere, myContributorFilters.get(contributor.getSearchProviderId()), progressIndicator); - fillUsages(foundElements, usages, targets); + try { + contributor + .fetchElements(searchText, everywhere, myContributorFilters.get(contributor.getSearchProviderId()), progressIndicator, + o -> { + if (progressIndicator.isCanceled()) { + return false; + } + + if (cached.contains(o)) { + return true; + } + + foundElements.add(o); + tooManyUsagesStatus.pauseProcessingIfTooManyUsages(); + if (foundElements.size() + alreadyFoundCount >= UsageLimitUtil.USAGES_LIMIT && + tooManyUsagesStatus.switchTooManyUsagesStatus()) { + int usageCount = foundElements.size() + alreadyFoundCount; + UsageViewManagerImpl + .showTooManyUsagesWarningLater(getProject(), tooManyUsagesStatus, progressIndicator, + presentation, usageCount, null); + return !progressIndicator.isCanceled(); + } + return true; + }); + } + catch (ProcessCanceledException e) { + return; + } } }); + fillUsages(foundElements, usages, targets); } @Override @@ -1093,18 +1127,18 @@ public class SearchEverywhereUI extends BorderLayoutPanel implements Disposable, } private void fillUsages(Collection foundElements, Collection usages, Collection targets) { - foundElements.stream() - .filter(o -> o instanceof PsiElement) - .forEach(o -> { - PsiElement element = (PsiElement)o; - if (element.getTextRange() != null) { - UsageInfo usageInfo = new UsageInfo(element); - usages.add(new UsageInfo2UsageAdapter(usageInfo)); - } - else { - targets.add(element); - } - }); + ReadAction.run(() -> foundElements.stream() + .filter(o -> o instanceof PsiElement) + .forEach(o -> { + PsiElement element = (PsiElement)o; + if (element.getTextRange() != null) { + UsageInfo usageInfo = new UsageInfo(element); + usages.add(new UsageInfo2UsageAdapter(usageInfo)); + } + else { + targets.add(element); + } + })); } private void showInFindWindow(Collection targets, Collection usages, UsageViewPresentation presentation) { From e86a9f810df6f33955fd5984ee06f0ee93f5213a Mon Sep 17 00:00:00 2001 From: Mikhail Sokolov Date: Thu, 6 Sep 2018 16:54:11 +0300 Subject: [PATCH 2/4] IDEA-198407 Add nullness annotations to base SearchEverywhereContributor class --- .../SearchEverywhereContributor.java | 39 +++++++++++++------ .../AbstractGotoSEContributor.java | 20 ++++++---- .../ActionSearchEverywhereContributor.java | 11 +++--- .../ClassSearchEverywhereContributor.java | 5 ++- .../FileSearchEverywhereContributor.java | 4 +- .../RecentFilesSEContributor.java | 7 ++-- .../SymbolSearchEverywhereContributor.java | 2 +- .../searcheverywhere/TopHitSEContributor.java | 12 +++--- .../MultithreadSearchTest.java | 22 ++++++----- .../YAMLKeysSearchEverywhereContributor.java | 11 +++--- 10 files changed, 80 insertions(+), 53 deletions(-) diff --git a/platform/lang-api/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereContributor.java b/platform/lang-api/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereContributor.java index c5f480e9554a..1546e99b0f4f 100644 --- a/platform/lang-api/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereContributor.java +++ b/platform/lang-api/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereContributor.java @@ -6,6 +6,7 @@ package com.intellij.ide.actions.searcheverywhere; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.progress.ProgressIndicator; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.ArrayList; @@ -16,7 +17,6 @@ import java.util.function.Function; /** * @author Konstantin Bulenkov */ -//todo generic? #UX-1 public interface SearchEverywhereContributor { ExtensionPointName> EP_NAME = ExtensionPointName.create("com.intellij.searchEverywhereContributor"); @@ -27,6 +27,7 @@ public interface SearchEverywhereContributor { @NotNull String getGroupName(); + @Nullable String includeNonProjectItemsText(); int getSortWeight(); @@ -37,15 +38,22 @@ public interface SearchEverywhereContributor { return false; } - default int getElementPriority(Object element, String searchPattern) { + default int getElementPriority(@NotNull Object element, @NotNull String searchPattern) { return 0; } - void fetchElements(String pattern, boolean everywhere, SearchEverywhereContributorFilter filter, - ProgressIndicator progressIndicator, Function consumer); + void fetchElements(@NotNull String pattern, + boolean everywhere, + @Nullable SearchEverywhereContributorFilter filter, + @NotNull ProgressIndicator progressIndicator, + @NotNull Function consumer); - default ContributorSearchResult search(String pattern, boolean everywhere, SearchEverywhereContributorFilter filter, - ProgressIndicator progressIndicator, int elementsLimit) { + @NotNull + default ContributorSearchResult search(@NotNull String pattern, + boolean everywhere, + @Nullable SearchEverywhereContributorFilter filter, + @NotNull ProgressIndicator progressIndicator, + int elementsLimit) { ContributorSearchResult.Builder builder = ContributorSearchResult.builder(); fetchElements(pattern, everywhere, filter, progressIndicator, element -> { if (elementsLimit < 0 || builder.itemsCount() < elementsLimit) { @@ -61,20 +69,26 @@ public interface SearchEverywhereContributor { return builder.build(); } - default List search(String pattern, boolean everywhere, SearchEverywhereContributorFilter filter, - ProgressIndicator progressIndicator) { + @NotNull + default List search(@NotNull String pattern, + boolean everywhere, + @Nullable SearchEverywhereContributorFilter filter, + @NotNull ProgressIndicator progressIndicator) { List res = new ArrayList<>(); fetchElements(pattern, everywhere, filter, progressIndicator, o -> res.add(o)); return res; } - boolean processSelectedItem(Object selected, int modifiers, String searchText); + boolean processSelectedItem(@NotNull Object selected, int modifiers, @NotNull String searchText); - ListCellRenderer getElementsRenderer(JList list); + @NotNull + ListCellRenderer getElementsRenderer(@NotNull JList list); - Object getDataForItem(Object element, String dataId); + @Nullable + Object getDataForItem(@NotNull Object element, @NotNull String dataId); - default String filterControlSymbols(String pattern) { + @NotNull + default String filterControlSymbols(@NotNull String pattern) { return pattern; } @@ -86,6 +100,7 @@ public interface SearchEverywhereContributor { return true; } + @NotNull static List> getProviders() { return Arrays.asList(EP_NAME.getExtensions()); } diff --git a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/AbstractGotoSEContributor.java b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/AbstractGotoSEContributor.java index 77ee174588e8..37d168ee8b15 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/AbstractGotoSEContributor.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/AbstractGotoSEContributor.java @@ -65,8 +65,8 @@ public abstract class AbstractGotoSEContributor implements SearchEverywhereCo private static final Logger LOG = Logger.getInstance(AbstractGotoSEContributor.class); @Override - public void fetchElements(String pattern, boolean everywhere, SearchEverywhereContributorFilter filter, - ProgressIndicator progressIndicator, Function consumer) { + public void fetchElements(@NotNull String pattern, boolean everywhere, @Nullable SearchEverywhereContributorFilter filter, + @NotNull ProgressIndicator progressIndicator, @NotNull Function consumer) { if (!isDumbModeSupported() && DumbService.getInstance(myProject).isDumb()) { return; } @@ -74,7 +74,9 @@ public abstract class AbstractGotoSEContributor implements SearchEverywhereCo String suffix = pattern.endsWith(fullMatchSearchSuffix) ? fullMatchSearchSuffix : ""; String searchString = filterControlSymbols(pattern) + suffix; FilteringGotoByModel model = createModel(myProject); - model.setFilterItems(filter.getSelectedElements()); + if (filter != null) { + model.setFilterItems(filter.getSelectedElements()); + } ChooseByNamePopup popup = ChooseByNamePopup.createPopup(myProject, model, (PsiElement)null); try { ApplicationManager.getApplication().runReadAction(() -> { @@ -95,8 +97,9 @@ public abstract class AbstractGotoSEContributor implements SearchEverywhereCo //todo param is unnecessary #UX-1 protected abstract FilteringGotoByModel createModel(Project project); + @NotNull @Override - public String filterControlSymbols(String pattern) { + public String filterControlSymbols(@NotNull String pattern) { if (StringUtil.containsAnyChar(pattern, ":,;@[( #") || pattern.contains(" line ") || pattern.contains("?l=")) { // quick test if reg exp should be used return applyPatternFilter(pattern, patternToDetectLinesAndColumns); } @@ -119,7 +122,7 @@ public abstract class AbstractGotoSEContributor implements SearchEverywhereCo } @Override - public boolean processSelectedItem(Object selected, int modifiers, String searchText) { + public boolean processSelectedItem(@NotNull Object selected, int modifiers, @NotNull String searchText) { if (selected instanceof PsiElement) { if (!((PsiElement)selected).isValid()) { LOG.warn("Cannot navigate to invalid PsiElement"); @@ -143,7 +146,7 @@ public abstract class AbstractGotoSEContributor implements SearchEverywhereCo } @Override - public Object getDataForItem(Object element, String dataId) { + public Object getDataForItem(@NotNull Object element, @NotNull String dataId) { if (CommonDataKeys.PSI_ELEMENT.is(dataId) && element instanceof PsiElement) { return element; } @@ -156,8 +159,9 @@ public abstract class AbstractGotoSEContributor implements SearchEverywhereCo return true; } + @NotNull @Override - public ListCellRenderer getElementsRenderer(JList list) { + public ListCellRenderer getElementsRenderer(@NotNull JList list) { return new SearchEverywherePsiRenderer(list) { @Override public String getElementText(PsiElement element) { @@ -172,7 +176,7 @@ public abstract class AbstractGotoSEContributor implements SearchEverywhereCo } @Override - public int getElementPriority(Object element, String searchPattern) { + public int getElementPriority(@NotNull Object element, @NotNull String searchPattern) { return 50; } diff --git a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/ActionSearchEverywhereContributor.java b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/ActionSearchEverywhereContributor.java index 1bd2e0bf0517..e59a0bdcea6c 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/ActionSearchEverywhereContributor.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/ActionSearchEverywhereContributor.java @@ -57,8 +57,8 @@ public class ActionSearchEverywhereContributor implements SearchEverywhereContri } @Override - public void fetchElements(String pattern, boolean everywhere, SearchEverywhereContributorFilter filter, - ProgressIndicator progressIndicator, Function consumer) { + public void fetchElements(@NotNull String pattern, boolean everywhere, @Nullable SearchEverywhereContributorFilter filter, + @NotNull ProgressIndicator progressIndicator, @NotNull Function consumer) { if (StringUtil.isEmptyOrSpaces(pattern)) { return; } @@ -80,8 +80,9 @@ public class ActionSearchEverywhereContributor implements SearchEverywhereContri } + @NotNull @Override - public ListCellRenderer getElementsRenderer(JList list) { + public ListCellRenderer getElementsRenderer(@NotNull JList list) { return new GotoActionModel.GotoActionListCellRenderer(myModel::getGroupName, true); } @@ -97,7 +98,7 @@ public class ActionSearchEverywhereContributor implements SearchEverywhereContri } @Override - public Object getDataForItem(Object element, String dataId) { + public Object getDataForItem(@NotNull Object element, @NotNull String dataId) { if (SetShortcutAction.SELECTED_ACTION.is(dataId)) { Object value = ((GotoActionModel.MatchedValue)element).value; if (value instanceof GotoActionModel.ActionWrapper) { @@ -113,7 +114,7 @@ public class ActionSearchEverywhereContributor implements SearchEverywhereContri } @Override - public boolean processSelectedItem(Object selected, int modifiers, String text) { + public boolean processSelectedItem(@NotNull Object selected, int modifiers, @NotNull String text) { selected = ((GotoActionModel.MatchedValue) selected).value; if (selected instanceof BooleanOptionDescription) { diff --git a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/ClassSearchEverywhereContributor.java b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/ClassSearchEverywhereContributor.java index 32dfd824a0e4..4759aff850b1 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/ClassSearchEverywhereContributor.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/ClassSearchEverywhereContributor.java @@ -60,8 +60,9 @@ public class ClassSearchEverywhereContributor extends AbstractGotoSEContributor< return new GotoClassModel2(project); } + @NotNull @Override - public String filterControlSymbols(String pattern) { + public String filterControlSymbols(@NotNull String pattern) { if (pattern.indexOf('#') != -1) { pattern = applyPatternFilter(pattern, patternToDetectMembers); } @@ -74,7 +75,7 @@ public class ClassSearchEverywhereContributor extends AbstractGotoSEContributor< } @Override - public int getElementPriority(Object element, String searchPattern) { + public int getElementPriority(@NotNull Object element, @NotNull String searchPattern) { return super.getElementPriority(element, searchPattern) + 5; } diff --git a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/FileSearchEverywhereContributor.java b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/FileSearchEverywhereContributor.java index 6488f7ff4478..4d196f2b67b3 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/FileSearchEverywhereContributor.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/FileSearchEverywhereContributor.java @@ -59,7 +59,7 @@ public class FileSearchEverywhereContributor extends AbstractGotoSEContributor filter, - ProgressIndicator progressIndicator, Function consumer) { + public void fetchElements(@NotNull String pattern, boolean everywhere, @Nullable SearchEverywhereContributorFilter filter, + @NotNull ProgressIndicator progressIndicator, @NotNull Function consumer) { String searchString = filterControlSymbols(pattern); MinusculeMatcher matcher = NameUtil.buildMatcher("*" + searchString).build(); List opened = Arrays.asList(FileEditorManager.getInstance(myProject).getSelectedFiles()); diff --git a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SymbolSearchEverywhereContributor.java b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SymbolSearchEverywhereContributor.java index 5c4b4ad675b1..95ccd656c525 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SymbolSearchEverywhereContributor.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SymbolSearchEverywhereContributor.java @@ -43,7 +43,7 @@ public class SymbolSearchEverywhereContributor extends AbstractGotoSEContributor } @Override - public int getElementPriority(Object element, String searchPattern) { + public int getElementPriority(@NotNull Object element, @NotNull String searchPattern) { return super.getElementPriority(element, searchPattern) + 3; } diff --git a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/TopHitSEContributor.java b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/TopHitSEContributor.java index 94ebb61a5890..7ee90e8d4e99 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/TopHitSEContributor.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/TopHitSEContributor.java @@ -28,6 +28,7 @@ import com.intellij.util.IconUtil; import com.intellij.util.ui.EmptyIcon; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.accessibility.Accessible; import javax.accessibility.AccessibleContext; @@ -80,18 +81,18 @@ public class TopHitSEContributor implements SearchEverywhereContributor { } @Override - public void fetchElements(String pattern, boolean everywhere, SearchEverywhereContributorFilter filter, - ProgressIndicator progressIndicator, Function consumer) { + public void fetchElements(@NotNull String pattern, boolean everywhere, @Nullable SearchEverywhereContributorFilter filter, + @NotNull ProgressIndicator progressIndicator, @NotNull Function consumer) { fill(pattern, consumer); } @Override - public Object getDataForItem(Object element, String dataId) { + public Object getDataForItem(@NotNull Object element, @NotNull String dataId) { return null; } @Override - public boolean processSelectedItem(Object selected, int modifiers, String text) { + public boolean processSelectedItem(@NotNull Object selected, int modifiers, @NotNull String text) { if (selected instanceof BooleanOptionDescription) { final BooleanOptionDescription option = (BooleanOptionDescription) selected; option.setOptionState(!option.isOptionEnabled()); @@ -111,8 +112,9 @@ public class TopHitSEContributor implements SearchEverywhereContributor { return false; } + @NotNull @Override - public ListCellRenderer getElementsRenderer(JList list) { + public ListCellRenderer getElementsRenderer(@NotNull JList list) { return new TopHitRenderer(myProject); } diff --git a/platform/lang-impl/testSources/com/intellij/ide/actions/searcheverywhere/MultithreadSearchTest.java b/platform/lang-impl/testSources/com/intellij/ide/actions/searcheverywhere/MultithreadSearchTest.java index 0f9c1d347e6e..8f8000fb183d 100644 --- a/platform/lang-impl/testSources/com/intellij/ide/actions/searcheverywhere/MultithreadSearchTest.java +++ b/platform/lang-impl/testSources/com/intellij/ide/actions/searcheverywhere/MultithreadSearchTest.java @@ -7,6 +7,7 @@ import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCa import com.intellij.util.Alarm; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.junit.Assert; import javax.swing.*; @@ -30,7 +31,7 @@ public class MultithreadSearchTest extends LightPlatformCodeInsightFixtureTestCa MultithreadSearcher searcher = new MultithreadSearcher(collector, command -> alarm.addRequest(command, 0)); scenarios.forEach(scenario -> { - searcher.search(scenario.contributorsAndLimits, null, false, ignrd -> null); + searcher.search(scenario.contributorsAndLimits, "", false, ignrd -> null); collector.awaitFinish(); scenario.results.forEach((contributorId, results) -> { List values = collector.getContributorValues(contributorId); @@ -47,7 +48,7 @@ public class MultithreadSearchTest extends LightPlatformCodeInsightFixtureTestCa SESearcher searcher = new SingleThreadSearcher(collector, command -> alarm.addRequest(command, 0)); scenarios.forEach(scenario -> { - searcher.search(scenario.contributorsAndLimits, null, false, ignrd -> null); + searcher.search(scenario.contributorsAndLimits, "", false, ignrd -> null); collector.awaitFinish(); scenario.results.forEach((contributorId, results) -> { List values = collector.getContributorValues(contributorId); @@ -344,16 +345,16 @@ public class MultithreadSearchTest extends LightPlatformCodeInsightFixtureTestCa } @Override - public int getElementPriority(Object element, String searchPattern) { + public int getElementPriority(@NotNull Object element, @NotNull String searchPattern) { return fixedPriority; } @Override - public void fetchElements(String pattern, + public void fetchElements(@NotNull String pattern, boolean everywhere, - SearchEverywhereContributorFilter filter, - ProgressIndicator progressIndicator, - Function consumer) { + @Nullable SearchEverywhereContributorFilter filter, + @NotNull ProgressIndicator progressIndicator, + @NotNull Function consumer) { boolean flag = true; Iterator iterator = Arrays.asList(items).iterator(); while (flag && iterator.hasNext()) { @@ -363,17 +364,18 @@ public class MultithreadSearchTest extends LightPlatformCodeInsightFixtureTestCa } @Override - public boolean processSelectedItem(Object selected, int modifiers, String searchText) { + public boolean processSelectedItem(@NotNull Object selected, int modifiers, @NotNull String searchText) { return false; } + @NotNull @Override - public ListCellRenderer getElementsRenderer(JList list) { + public ListCellRenderer getElementsRenderer(@NotNull JList list) { return null; } @Override - public Object getDataForItem(Object element, String dataId) { + public Object getDataForItem(@NotNull Object element, @NotNull String dataId) { return null; } }; diff --git a/plugins/yaml/src/org/jetbrains/yaml/navigation/YAMLKeysSearchEverywhereContributor.java b/plugins/yaml/src/org/jetbrains/yaml/navigation/YAMLKeysSearchEverywhereContributor.java index 9a678820388a..939c629008ac 100644 --- a/plugins/yaml/src/org/jetbrains/yaml/navigation/YAMLKeysSearchEverywhereContributor.java +++ b/plugins/yaml/src/org/jetbrains/yaml/navigation/YAMLKeysSearchEverywhereContributor.java @@ -72,8 +72,8 @@ public class YAMLKeysSearchEverywhereContributor implements SearchEverywhereCont } @Override - public void fetchElements(String pattern, boolean everywhere, SearchEverywhereContributorFilter filter, - ProgressIndicator progressIndicator, Function consumer) { + public void fetchElements(@NotNull String pattern, boolean everywhere, @Nullable SearchEverywhereContributorFilter filter, + @NotNull ProgressIndicator progressIndicator, @NotNull Function consumer) { if (myProject == null || DumbService.getInstance(myProject).isDumb() || pattern.isEmpty()) { return; } @@ -82,20 +82,21 @@ public class YAMLKeysSearchEverywhereContributor implements SearchEverywhereCont } @Override - public boolean processSelectedItem(Object selected, int modifiers, String searchText) { + public boolean processSelectedItem(@NotNull Object selected, int modifiers, @NotNull String searchText) { if (selected instanceof Navigatable) { ((Navigatable)selected).navigate(true); } return true; } + @NotNull @Override - public ListCellRenderer getElementsRenderer(JList list) { + public ListCellRenderer getElementsRenderer(@NotNull JList list) { return new NavigationItemListCellRenderer(); } @Override - public Object getDataForItem(Object element, String dataId) { + public Object getDataForItem(@NotNull Object element, @NotNull String dataId) { return null; } From ae8e849800eb899dff2cd44c75eaa12df4800647 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Thu, 6 Sep 2018 15:51:43 +0200 Subject: [PATCH 3/4] =?UTF-8?q?get=20rid=20of=20manual=20XML=20read/write?= =?UTF-8?q?=20=E2=80=94=20ShortenCommandLine.readShortenClasspathMethod,?= =?UTF-8?q?=20support=20enum=20in=20DSL=20(schema=20and=20read)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../execution/JavaTestConfigurationBase.java | 2 +- .../application/ApplicationConfiguration.java | 32 ++++++--- .../JvmMainMethodRunConfigurationOptions.kt | 16 +++-- .../TestDiscoveryConfigurationProducer.java | 2 +- .../execution/ShortenCommandLine.java | 15 +--- .../configurations/RunConfigurationBase.java | 4 +- ...ConfigurationWithCommandLineShortener.java | 4 +- .../properties/ObjectStoredProperty.kt | 30 +++++++- .../intellij/openapi/components/BaseState.kt | 70 +++++++++---------- .../intellij/util/xmlb/XmlSerializerImpl.java | 16 +---- .../intellij/util/xmlb/XmlSerializerUtil.java | 35 ++++++---- .../configurationScript/JsonBuilder.kt | 12 +++- .../RunConfigurationJsonSchemaGenerator.kt | 31 +++++++- .../RunConfigurationListReader.kt | 2 +- ...kt => runConfigurationTemplateProvider.kt} | 0 .../test/ConfigurationFileTest.kt | 2 +- .../test/PropertyValueReaderTest.kt | 28 ++++++++ 17 files changed, 196 insertions(+), 105 deletions(-) rename plugins/configuration-script/src/com/intellij/configurationScript/{IntellijConfigurationAppInitializer.kt => runConfigurationTemplateProvider.kt} (100%) create mode 100644 plugins/configuration-script/test/PropertyValueReaderTest.kt diff --git a/java/execution/impl/src/com/intellij/execution/JavaTestConfigurationBase.java b/java/execution/impl/src/com/intellij/execution/JavaTestConfigurationBase.java index 8b1071d46365..c62e4df950dd 100644 --- a/java/execution/impl/src/com/intellij/execution/JavaTestConfigurationBase.java +++ b/java/execution/impl/src/com/intellij/execution/JavaTestConfigurationBase.java @@ -61,7 +61,7 @@ public abstract class JavaTestConfigurationBase extends ModuleBasedConfiguration } @Override - public void setShortenCommandLine(ShortenCommandLine shortenCommandLine) { + public void setShortenCommandLine(@Nullable ShortenCommandLine shortenCommandLine) { myShortenCommandLine = shortenCommandLine; } diff --git a/java/execution/impl/src/com/intellij/execution/application/ApplicationConfiguration.java b/java/execution/impl/src/com/intellij/execution/application/ApplicationConfiguration.java index b8b59f2c269b..7e68cc96c331 100644 --- a/java/execution/impl/src/com/intellij/execution/application/ApplicationConfiguration.java +++ b/java/execution/impl/src/com/intellij/execution/application/ApplicationConfiguration.java @@ -9,6 +9,7 @@ import com.intellij.execution.junit.RefactoringListeners; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.util.JavaParametersUtil; import com.intellij.execution.util.ProgramParametersUtil; +import com.intellij.openapi.components.BaseState; import com.intellij.openapi.module.Module; import com.intellij.openapi.options.SettingsEditor; import com.intellij.openapi.options.SettingsEditorGroup; @@ -35,14 +36,18 @@ public class ApplicationConfiguration extends ModuleBasedConfiguration by property(LinkedHashMap()) + + // see ConfigurationWithCommandLineShortener - "null if option was not selected explicitly, legacy user-local options to be used" + // so, we cannot use NONE as default value + @get:OptionTag(nameAttribute = "", valueAttribute = "name") + var shortenClasspath by enum() } \ No newline at end of file diff --git a/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryConfigurationProducer.java b/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryConfigurationProducer.java index 5882168506e6..c0f5d5b8a232 100644 --- a/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryConfigurationProducer.java +++ b/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryConfigurationProducer.java @@ -238,7 +238,7 @@ public abstract class TestDiscoveryConfigurationProducer extends JavaRunConfigur } @Override - public void setShortenCommandLine(ShortenCommandLine mode) { + public void setShortenCommandLine(@Nullable ShortenCommandLine mode) { myConfiguration.setShortenCommandLine(mode); } diff --git a/platform/lang-api/src/com/intellij/execution/ShortenCommandLine.java b/platform/lang-api/src/com/intellij/execution/ShortenCommandLine.java index 071b77d9b38b..dbc2bcb19587 100644 --- a/platform/lang-api/src/com/intellij/execution/ShortenCommandLine.java +++ b/platform/lang-api/src/com/intellij/execution/ShortenCommandLine.java @@ -1,16 +1,4 @@ -// Copyright 2000-2017 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. +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.execution; import com.intellij.openapi.project.Project; @@ -74,6 +62,7 @@ public enum ShortenCommandLine { return null; } + @Deprecated public static void writeShortenClasspathMethod(@NotNull Element element, ShortenCommandLine shortenCommandLine) { if (shortenCommandLine != null) { element.addContent(new Element("shortenClasspath").setAttribute("name", shortenCommandLine.name())); diff --git a/platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationBase.java b/platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationBase.java index 91d791b83257..55065a910c6c 100644 --- a/platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationBase.java +++ b/platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationBase.java @@ -21,6 +21,7 @@ import com.intellij.util.SmartList; import com.intellij.util.xmlb.annotations.Attribute; import com.intellij.util.xmlb.annotations.Transient; import org.jdom.Element; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -215,7 +216,8 @@ public abstract class RunConfigurationBase extends UserDataHolderBase implements myOptions = XmlSerializer.deserialize(element, getOptionsClass()); } - public final void setState(@NotNull BaseState state) { + @ApiStatus.Experimental + public void setState(@NotNull BaseState state) { myOptions = (RunConfigurationOptions)state; } diff --git a/platform/lang-impl/src/com/intellij/execution/ConfigurationWithCommandLineShortener.java b/platform/lang-impl/src/com/intellij/execution/ConfigurationWithCommandLineShortener.java index 9055106d22f5..65f655c5db41 100644 --- a/platform/lang-impl/src/com/intellij/execution/ConfigurationWithCommandLineShortener.java +++ b/platform/lang-impl/src/com/intellij/execution/ConfigurationWithCommandLineShortener.java @@ -1,4 +1,4 @@ -// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.execution; import com.intellij.openapi.project.Project; @@ -14,7 +14,7 @@ public interface ConfigurationWithCommandLineShortener { /** * Called from UI, when user explicitly selects method to be used to shorten the command line or from the deserialization */ - void setShortenCommandLine(ShortenCommandLine mode); + void setShortenCommandLine(@Nullable ShortenCommandLine mode); Project getProject(); } diff --git a/platform/projectModel-api/src/com/intellij/configurationStore/properties/ObjectStoredProperty.kt b/platform/projectModel-api/src/com/intellij/configurationStore/properties/ObjectStoredProperty.kt index b4df3632b732..f7222d35dfd6 100644 --- a/platform/projectModel-api/src/com/intellij/configurationStore/properties/ObjectStoredProperty.kt +++ b/platform/projectModel-api/src/com/intellij/configurationStore/properties/ObjectStoredProperty.kt @@ -4,9 +4,10 @@ package com.intellij.configurationStore.properties import com.intellij.openapi.components.* import com.intellij.openapi.util.ModificationTracker import com.intellij.openapi.util.text.StringUtil +import com.intellij.util.xmlb.XmlSerializerUtil import kotlin.reflect.KProperty -internal abstract class ObjectStateStoredPropertyBase(protected var value: T) : StoredPropertyBase() { +abstract class ObjectStateStoredPropertyBase(protected var value: T) : StoredPropertyBase() { override val jsonType: JsonSchemaType get() = JsonSchemaType.OBJECT @@ -55,6 +56,33 @@ internal open class ObjectStoredProperty(private val defaultValue: T) : Objec } } +class EnumStoredProperty>(private val defaultValue: T?, val clazz: Class) : ObjectStateStoredPropertyBase(defaultValue), ScalarProperty { + override val jsonType: JsonSchemaType + get() = JsonSchemaType.STRING + + override fun isEqualToDefault() = value === defaultValue + + override fun getModificationCount() = 0L + + override fun setValue(thisRef: BaseState, property: KProperty<*>, @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") newValue: T?) { + val v = newValue ?: defaultValue + if (value !== v) { + thisRef.intIncrementModificationCount() + value = v + } + } + + @Suppress("UNCHECKED_CAST") + override fun parseAndSetValue(rawValue: String?) { + if (rawValue == null) { + value = defaultValue + } + else { + value = XmlSerializerUtil.stringToEnum(rawValue, clazz, true /* lowercase in YAML by default */) as T? ?: defaultValue + } + } +} + internal class StateObjectStoredProperty(initialValue: T) : ObjectStateStoredPropertyBase(initialValue) { override fun isEqualToDefault(): Boolean { val value = value diff --git a/platform/projectModel-api/src/com/intellij/openapi/components/BaseState.kt b/platform/projectModel-api/src/com/intellij/openapi/components/BaseState.kt index d5151f17e3e3..a269963a5d54 100644 --- a/platform/projectModel-api/src/com/intellij/openapi/components/BaseState.kt +++ b/platform/projectModel-api/src/com/intellij/openapi/components/BaseState.kt @@ -32,7 +32,7 @@ abstract class BaseState : SerializationFilter, ModificationTracker { properties.add(p as StoredProperty) } - fun property(): StoredPropertyBase { + protected fun property(): StoredPropertyBase { val result = ObjectStoredProperty(null) addProperty(result) return result @@ -42,7 +42,7 @@ abstract class BaseState : SerializationFilter, ModificationTracker { * Value considered as default only if all properties have default values. * Passed instance is not used for `isDefault` check. It is just an initial value. */ - fun property(initialValue: T): StoredPropertyBase { + protected fun property(initialValue: T): StoredPropertyBase { val result = StateObjectStoredProperty(initialValue) addProperty(result) return result @@ -51,7 +51,7 @@ abstract class BaseState : SerializationFilter, ModificationTracker { /** * For non-BaseState classes explicit `isDefault` must be provided, because no other way to check. */ - fun property(initialValue: T, isDefault: (value: T) -> Boolean): StoredPropertyBase { + protected fun property(initialValue: T, isDefault: (value: T) -> Boolean): StoredPropertyBase { val result = object : ObjectStoredProperty(initialValue) { override fun isEqualToDefault() = isDefault(value) } @@ -64,7 +64,7 @@ abstract class BaseState : SerializationFilter, ModificationTracker { * Collection considered as default if empty. It is *your* responsibility to call `incrementModificationCount` on collection modification. * You cannot set value to a new collection - on set current collection is cleared and new collection is added to current. */ - fun > property(initialValue: C): StoredPropertyBase { + protected fun > property(initialValue: C): StoredPropertyBase { val result = CollectionStoredProperty(initialValue) addProperty(result) return result @@ -73,7 +73,7 @@ abstract class BaseState : SerializationFilter, ModificationTracker { /** * Charset is an immutable, so, it is safe to use it as default value. */ - fun property(initialValue: T): StoredPropertyBase { + protected fun property(initialValue: T): StoredPropertyBase { val result = ObjectStoredProperty(initialValue) addProperty(result) return result @@ -82,27 +82,41 @@ abstract class BaseState : SerializationFilter, ModificationTracker { /** * Enum is an immutable, so, it is safe to use it as default value. */ - fun > property(defaultValue: T): StoredPropertyBase { + protected fun > property(defaultValue: T): StoredPropertyBase { val result = ObjectStoredProperty(defaultValue) addProperty(result) return result } + /** + * `null` is always normalized to null. + */ + protected inline fun > enum(defaultValue: T? = null): StoredPropertyBase { + return doEnum(defaultValue, T::class.java) + } + + @PublishedApi + internal fun > doEnum(defaultValue: T? = null, clazz: Class): StoredPropertyBase { + val result = EnumStoredProperty(defaultValue, clazz) + addProperty(result) + return result + } + /** * Not-null list. Initialized as SmartList. */ - fun list(): StoredPropertyBase> { + protected fun list(): StoredPropertyBase> { val result = ListStoredProperty() addProperty(result) @Suppress("UNCHECKED_CAST") return result as StoredPropertyBase> } - fun property(value: MutableMap): StoredPropertyBase> { + protected fun property(value: MutableMap): StoredPropertyBase> { return map(value) } - fun map(value: MutableMap = THashMap()): StoredPropertyBase> { + protected fun map(value: MutableMap = THashMap()): StoredPropertyBase> { val result = MapStoredProperty(value) addProperty(result) return result @@ -111,36 +125,36 @@ abstract class BaseState : SerializationFilter, ModificationTracker { /** * Empty string is always normalized to null. */ - fun property(defaultValue: String?): StoredPropertyBase = string(defaultValue) + protected fun property(defaultValue: String?): StoredPropertyBase = string(defaultValue) /** * Empty string is always normalized to null. */ - fun string(defaultValue: String? = null): StoredPropertyBase { + protected fun string(defaultValue: String? = null): StoredPropertyBase { val result = NormalizedStringStoredProperty(defaultValue) addProperty(result) return result } - fun property(defaultValue: Int = 0): StoredPropertyBase { + protected fun property(defaultValue: Int = 0): StoredPropertyBase { val result = IntStoredProperty(defaultValue, null) addProperty(result) return result } - fun property(defaultValue: Long = 0): StoredPropertyBase { + protected fun property(defaultValue: Long = 0): StoredPropertyBase { val result = LongStoredProperty(defaultValue, null) addProperty(result) return result } - fun property(defaultValue: Float = 0f, valueNormalizer: ((value: Float) -> Float)? = null): StoredPropertyBase { + protected fun property(defaultValue: Float = 0f, valueNormalizer: ((value: Float) -> Float)? = null): StoredPropertyBase { val result = FloatStoredProperty(defaultValue, valueNormalizer) addProperty(result) return result } - fun property(defaultValue: Boolean = false): StoredPropertyBase { + protected fun property(defaultValue: Boolean = false): StoredPropertyBase { val result = ObjectStoredProperty(defaultValue) addProperty(result) return result @@ -217,26 +231,8 @@ abstract class BaseState : SerializationFilter, ModificationTracker { } } - fun getProperties() = properties -} - -// move buildJsonSchema and other such functions from BaseState to exclude from completion -// internal usage only -@ApiStatus.Experimental -fun buildJsonSchema(state: BaseState, builder: StringBuilder) { - val properties = state.getProperties() - // todo object definition - for (property in properties) { - builder.jsonEscapedString(property.name!!).append(':').append('{') - builder.jsonEscapedString("type").append(':').jsonEscapedString(property.jsonType.jsonName) - builder.append('}') - if (property !== properties.last()) { - builder.append(',') - } - } -} - -private fun StringBuilder.jsonEscapedString(value: String): StringBuilder { - append('"').append(value).append('"') - return this + // internal usage only + @Suppress("FunctionName") + @ApiStatus.Experimental + fun __getProperties() = properties } \ No newline at end of file diff --git a/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java b/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java index cae26e096199..9eee32801287 100644 --- a/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java +++ b/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java @@ -255,20 +255,8 @@ public final class XmlSerializerImpl { accessor.setShort(host, Short.parseShort(value)); } else if (valueClass.isEnum()) { - Object deserializedValue = null; - for (Object enumConstant : valueClass.getEnumConstants()) { - if (enumConstant.toString().equals(value)) { - deserializedValue = enumConstant; - } - } - if (deserializedValue == null) { - for (Object enumConstant : valueClass.getEnumConstants()) { - if (enumConstant.toString().equalsIgnoreCase(value)) { - deserializedValue = enumConstant; - } - } - } - accessor.set(host, deserializedValue); + //noinspection unchecked + accessor.set(host, XmlSerializerUtil.stringToEnum(value, (Class>)valueClass, false)); } else if (Date.class.isAssignableFrom(valueClass)) { try { diff --git a/platform/util/src/com/intellij/util/xmlb/XmlSerializerUtil.java b/platform/util/src/com/intellij/util/xmlb/XmlSerializerUtil.java index 3638e21d2c57..2e3389c11d14 100644 --- a/platform/util/src/com/intellij/util/xmlb/XmlSerializerUtil.java +++ b/platform/util/src/com/intellij/util/xmlb/XmlSerializerUtil.java @@ -1,22 +1,9 @@ -/* - * Copyright 2000-2015 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.util.xmlb; import com.intellij.util.ReflectionUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; @@ -48,4 +35,22 @@ public class XmlSerializerUtil { public static List getAccessors(@NotNull Class aClass) { return BeanBinding.getAccessors(aClass); } + + @Nullable + public static Object stringToEnum(@NotNull String value, @NotNull Class> valueClass, boolean isAlwaysIgnoreCase) { + Enum[] enumConstants = valueClass.getEnumConstants(); + if (!isAlwaysIgnoreCase) { + for (Object enumConstant : enumConstants) { + if (enumConstant.toString().equals(value)) { + return enumConstant; + } + } + } + for (Object enumConstant : enumConstants) { + if (enumConstant.toString().equalsIgnoreCase(value)) { + return enumConstant; + } + } + return null; + } } diff --git a/plugins/configuration-script/src/com/intellij/configurationScript/JsonBuilder.kt b/plugins/configuration-script/src/com/intellij/configurationScript/JsonBuilder.kt index 643c11907669..20d1b6900813 100644 --- a/plugins/configuration-script/src/com/intellij/configurationScript/JsonBuilder.kt +++ b/plugins/configuration-script/src/com/intellij/configurationScript/JsonBuilder.kt @@ -76,16 +76,24 @@ internal class JsonObjectBuilder(private val builder: StringBuilder) { } fun rawMap(key: CharSequence, build: (StringBuilder) -> Unit) { + mapOrArray('{', '}', key, build) + } + + fun rawArray(key: CharSequence, build: (StringBuilder) -> Unit) { + mapOrArray('[', ']', key, build) + } + + private fun mapOrArray(openChar: Char, closeChar: Char, key: CharSequence, build: (StringBuilder) -> Unit) { builder .appendCommaIfNeed() .jsonEscapedString(key) .append(':') - .append('{') + .append(openChar) .append('\n') build(builder) builder .append('\n') - .append('}') + .append(closeChar) } fun rawBuilder(key: CharSequence, child: JsonObjectBuilder) { diff --git a/plugins/configuration-script/src/com/intellij/configurationScript/RunConfigurationJsonSchemaGenerator.kt b/plugins/configuration-script/src/com/intellij/configurationScript/RunConfigurationJsonSchemaGenerator.kt index f24eb43ddbf5..e6b063d4dd76 100644 --- a/plugins/configuration-script/src/com/intellij/configurationScript/RunConfigurationJsonSchemaGenerator.kt +++ b/plugins/configuration-script/src/com/intellij/configurationScript/RunConfigurationJsonSchemaGenerator.kt @@ -1,8 +1,9 @@ package com.intellij.configurationScript +import com.intellij.configurationStore.properties.EnumStoredProperty import com.intellij.execution.configurations.ConfigurationFactory import com.intellij.execution.configurations.ConfigurationType -import com.intellij.openapi.components.buildJsonSchema +import com.intellij.openapi.components.BaseState import com.intellij.openapi.diagnostic.debug import com.intellij.openapi.util.text.StringUtil import com.intellij.util.ReflectionUtil @@ -175,12 +176,38 @@ internal class RunConfigurationJsonSchemaGenerator { if (description != null) { "description" toUnescaped description } - rawMap("properties") { buildJsonSchema(state, it) } + map("properties") { buildJsonSchema(state, this) } } "additionalProperties" to false } } +// move buildJsonSchema and other such functions from BaseState to exclude from completion +private fun buildJsonSchema(state: BaseState, builder: JsonObjectBuilder) { + val properties = state.__getProperties() + // todo object definition + for (property in properties) { + builder.map(property.name!!) { + "type" to property.jsonType.jsonName + if (property is EnumStoredProperty<*>) { + describeEnum(property) + } + } + } +} + +private fun JsonObjectBuilder.describeEnum(property: EnumStoredProperty<*>) { + rawArray("enum") { stringBuilder -> + val enumConstants = property.clazz.enumConstants + for (enum in enumConstants) { + stringBuilder.append('"').append(enum.toString().toLowerCase()).append('"') + if (enum !== enumConstants.last()) { + stringBuilder.append(',') + } + } + } +} + // returns null if id is not valid internal fun rcTypeIdToPropertyName(configurationType: ConfigurationType): CharSequence? { val result = idToPropertyName(configurationType.tag, configurationType, null) ?: return null diff --git a/plugins/configuration-script/src/com/intellij/configurationScript/RunConfigurationListReader.kt b/plugins/configuration-script/src/com/intellij/configurationScript/RunConfigurationListReader.kt index a2eb95a1ffad..1ad015ad5a17 100644 --- a/plugins/configuration-script/src/com/intellij/configurationScript/RunConfigurationListReader.kt +++ b/plugins/configuration-script/src/com/intellij/configurationScript/RunConfigurationListReader.kt @@ -107,7 +107,7 @@ internal class RunConfigurationListReader(private val processor: (factory: Confi private fun readRc(optionsClass: Class, node: MappingNode, factory: ConfigurationFactory) { val state = ReflectionUtil.newInstance(optionsClass) - val properties = state.getProperties() + val properties = state.__getProperties() for (tuple in node.value) { val valueNode = tuple.valueNode val key = (tuple.keyNode as ScalarNode).value diff --git a/plugins/configuration-script/src/com/intellij/configurationScript/IntellijConfigurationAppInitializer.kt b/plugins/configuration-script/src/com/intellij/configurationScript/runConfigurationTemplateProvider.kt similarity index 100% rename from plugins/configuration-script/src/com/intellij/configurationScript/IntellijConfigurationAppInitializer.kt rename to plugins/configuration-script/src/com/intellij/configurationScript/runConfigurationTemplateProvider.kt diff --git a/plugins/configuration-script/test/ConfigurationFileTest.kt b/plugins/configuration-script/test/ConfigurationFileTest.kt index 2204f9568ef5..6559434353d8 100644 --- a/plugins/configuration-script/test/ConfigurationFileTest.kt +++ b/plugins/configuration-script/test/ConfigurationFileTest.kt @@ -119,7 +119,7 @@ class ConfigurationFileTest { } } -private fun parse(@Language("YAML") data: String, isTemplatesOnly: Boolean = false): List { +internal fun parse(@Language("YAML") data: String, isTemplatesOnly: Boolean = false): List { val list = SmartList() parseConfigurationFile(data.trimIndent().reader(), isTemplatesOnly) { _, state -> list.add(state) diff --git a/plugins/configuration-script/test/PropertyValueReaderTest.kt b/plugins/configuration-script/test/PropertyValueReaderTest.kt new file mode 100644 index 000000000000..c3f521c488d2 --- /dev/null +++ b/plugins/configuration-script/test/PropertyValueReaderTest.kt @@ -0,0 +1,28 @@ +package com.intellij.configurationScript + +import com.intellij.execution.ShortenCommandLine +import com.intellij.execution.application.JvmMainMethodRunConfigurationOptions +import com.intellij.testFramework.ProjectRule +import com.intellij.testFramework.assertions.Assertions.assertThat +import org.junit.ClassRule +import org.junit.Test + +class PropertyValueReaderTest { + companion object { + @JvmField + @ClassRule + val projectRule = ProjectRule() + } + + @Test + fun `enum`() { + val result = parse(""" + runConfigurations: + jvmMainMethod: + shortenClasspath: MANIFEST + """) + val options = JvmMainMethodRunConfigurationOptions() + options.shortenClasspath = ShortenCommandLine.MANIFEST + assertThat(result).containsExactly(options) + } +} \ No newline at end of file From e5f5a1787ea471bd0897d7c8f46d88847bbb3a03 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Thu, 6 Sep 2018 16:05:25 +0200 Subject: [PATCH 4/4] cleanup --- .../com/intellij/openapi/wm/impl/ProjectFrameBounds.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectFrameBounds.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectFrameBounds.kt index edb90335a6ab..fb6c1e9643cc 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectFrameBounds.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectFrameBounds.kt @@ -16,7 +16,7 @@ import java.awt.Rectangle class ProjectFrameBounds(private val project: Project) : PersistentStateComponent, ModificationTracker { companion object { @JvmStatic - fun getInstance(project: Project): ProjectFrameBounds = project.service() + fun getInstance(project: Project) = project.service() } // in device space @@ -26,7 +26,7 @@ class ProjectFrameBounds(private val project: Project) : PersistentStateComponen val isInFullScreen: Boolean get() = rawFrameInfo?.fullScreen ?: false - override fun getState(): FrameInfo? = rawFrameInfo + override fun getState() = rawFrameInfo override fun loadState(state: FrameInfo) { rawFrameInfo = state @@ -49,10 +49,10 @@ class ProjectFrameBounds(private val project: Project) : PersistentStateComponen class FrameInfo : BaseState() { // flat is used due to backward compatibility - @get:Property(flat = true) var bounds: Rectangle? by property() - @get:Attribute var extendedState: Int by property(Frame.NORMAL) + @get:Property(flat = true) var bounds by property() + @get:Attribute var extendedState by property(Frame.NORMAL) - @get:Attribute var fullScreen: Boolean by property(false) + @get:Attribute var fullScreen by property(false) } fun WindowManagerImpl.getFrameInfoInDeviceSpace(project: Project): FrameInfo? {