diff --git a/build/conf/nsis/idea.nsi b/build/conf/nsis/idea.nsi index 46c084bffd08..1a6be5c9c658 100644 --- a/build/conf/nsis/idea.nsi +++ b/build/conf/nsis/idea.nsi @@ -973,6 +973,15 @@ Function un.ConfirmDeleteSettings !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 3" "Text" "$(text_delete_settings)" !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 4" "Text" "$(confirm_delete_caches)" !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 5" "Text" "$(confirm_delete_settings)" + StrCmp "${UNINSTALL_WEB_PAGE}" "feedback_web_page" hide_feedback_checkbox done +hide_feedback_checkbox: + ; do not show feedback web page checkbox through products uninstall. + push $R1 + !insertmacro INSTALLOPTIONS_READ $R1 "DeleteSettings.ini" "Settings" "NumFields" + IntOp $R1 $R1 - 1 + !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Settings" "NumFields" "$R1" + pop $R1 +done: !insertmacro INSTALLOPTIONS_DISPLAY "DeleteSettings.ini" FunctionEnd @@ -1181,9 +1190,9 @@ remove_IntelliJIdeaProjectFile: done: DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" ; UNCOMMENT THIS IN RELEASE BUILD + StrCmp "${UNINSTALL_WEB_PAGE}" "feedback_web_page" end_of_uninstall !insertmacro INSTALLOPTIONS_READ $R3 "DeleteSettings.ini" "Field 6" "State" StrCmp "$R3" "0" end_of_uninstall - StrCmp "${UNINSTALL_WEB_PAGE}" "NotRequired" end_of_uninstall ExecShell "" "${UNINSTALL_WEB_PAGE}" end_of_uninstall: SectionEnd diff --git a/build/conf/nsis/strings.nsi b/build/conf/nsis/strings.nsi index 9672e05753bf..76db8dd9bf31 100644 --- a/build/conf/nsis/strings.nsi +++ b/build/conf/nsis/strings.nsi @@ -6,6 +6,8 @@ !define PRODUCT_UNINST_ICON_FILE "idea_uninst.ico" !define PRODUCT_LOGO_FILE "logo.bmp" !define PRODUCT_HEADER_FILE "headerlogo.bmp" +!define ASSOCIATION ".java" +!define UNINSTALL_WEB_PAGE "https://www.jetbrains.com/idea/uninstall/?edition=IU-__VERSION_MAJOR__.__VERSION_MINOR__" ; if SHOULD_SET_DEFAULT_INSTDIR != 0 then default installation directory will be directory where highest-numbered IDEA build has been installed ; set to 1 for release build diff --git a/build/conf/nsis/stringsCE.nsi b/build/conf/nsis/stringsCE.nsi index 3053ade3094e..3c9247bc1160 100644 --- a/build/conf/nsis/stringsCE.nsi +++ b/build/conf/nsis/stringsCE.nsi @@ -6,6 +6,8 @@ !define PRODUCT_UNINST_ICON_FILE "idea_CEuninst.ico" !define PRODUCT_LOGO_FILE "logoCE.bmp" !define PRODUCT_HEADER_FILE "headerlogoCE.bmp" +!define ASSOCIATION ".java" +!define UNINSTALL_WEB_PAGE "https://www.jetbrains.com/idea/uninstall/?edition=IC-__VERSION_MAJOR__.__VERSION_MINOR__" ; if SHOULD_SET_DEFAULT_INSTDIR != 0 then default installation directory will be directory where highest-numbered IDEA build has been installed ; set to 1 for release build diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java index 20f0cb122cad..24224f93c530 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java @@ -26,10 +26,7 @@ import com.intellij.debugger.engine.events.SuspendContextCommandImpl; import com.intellij.debugger.engine.jdi.ThreadReferenceProxy; import com.intellij.debugger.engine.requests.MethodReturnValueWatcher; import com.intellij.debugger.engine.requests.RequestManagerImpl; -import com.intellij.debugger.impl.DebuggerContextImpl; -import com.intellij.debugger.impl.DebuggerSession; -import com.intellij.debugger.impl.DebuggerUtilsEx; -import com.intellij.debugger.impl.PrioritizedTask; +import com.intellij.debugger.impl.*; import com.intellij.debugger.jdi.StackFrameProxyImpl; import com.intellij.debugger.jdi.ThreadReferenceProxyImpl; import com.intellij.debugger.jdi.VirtualMachineProxyImpl; @@ -89,6 +86,7 @@ import javax.swing.*; import java.io.IOException; import java.net.UnknownHostException; import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; public abstract class DebugProcessImpl extends UserDataHolderBase implements DebugProcess { @@ -1852,7 +1850,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb final Semaphore semaphore = new Semaphore(); semaphore.down(); - final Ref connectorIsReady = Ref.create(false); + final AtomicBoolean connectorIsReady = new AtomicBoolean(false); myDebugProcessDispatcher.addListener(new DebugProcessAdapter() { @Override public void connectorIsReady() { @@ -1890,17 +1888,17 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb } else { fail(); - if (myExecutionResult != null || !connectorIsReady.get()) { - // propagate exception only in case we succeeded to obtain execution result, - // otherwise if the error is induced by the fact that there is nothing to debug, and there is no need to show - // this problem to the user - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { + DebuggerInvocationUtil.swingInvokeLater(myProject, new Runnable() { + @Override + public void run() { + // propagate exception only in case we succeeded to obtain execution result, + // otherwise if the error is induced by the fact that there is nothing to debug, and there is no need to show + // this problem to the user + if (myExecutionResult != null || !connectorIsReady.get()) { ExecutionUtil.handleExecutionError(myProject, ToolWindowId.DEBUG, sessionName, e); } - }); - } + } + }); break; } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java index deacd9209c0f..f3f35619dffa 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java @@ -88,6 +88,7 @@ public class HighlightMethodUtil { PsiMethod superMethod = superMethodSignature.getMethod(); if (method.hasModifierProperty(PsiModifier.ABSTRACT) && !MethodSignatureUtil.isSuperMethod(superMethod, method)) continue; if (!PsiUtil.isAccessible(containingFile.getProject(), superMethod, method, null)) continue; + if (!includeRealPositionInfo && MethodSignatureUtil.isSuperMethod(superMethod, method)) continue; HighlightInfo info = isWeaker(method, modifierList, accessModifier, accessLevel, superMethod, includeRealPositionInfo); if (info != null) return info; } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreatePropertyFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreatePropertyFromUsageFix.java index ac2e35b9b776..72b608bfce94 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreatePropertyFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreatePropertyFromUsageFix.java @@ -37,7 +37,9 @@ import com.intellij.psi.codeStyle.VariableKind; import com.intellij.psi.util.PropertyUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; +import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -120,12 +122,17 @@ public class CreatePropertyFromUsageFix extends CreateFromUsageBaseFix implement private final String myDefaultFieldName; private final PsiField myField; private final PsiClass myClass; - private final PsiType[] myExpectedTypes; + private final List myExpectedTypes; - public FieldExpression(PsiField field, PsiClass aClass, PsiType[] expectedTypes) { + public FieldExpression(final PsiField field, PsiClass aClass, PsiType[] expectedTypes) { myField = field; myClass = aClass; - myExpectedTypes = expectedTypes; + myExpectedTypes = ContainerUtil.map(expectedTypes, new Function() { + @Override + public SmartTypePointer fun(PsiType type) { + return SmartTypePointerManager.getInstance(field.getProject()).createSmartTypePointer(type); + } + }); myDefaultFieldName = field.getName(); } @@ -143,12 +150,11 @@ public class CreatePropertyFromUsageFix extends CreateFromUsageBaseFix implement public LookupElement[] calculateLookupItems(ExpressionContext context) { Set set = new LinkedHashSet(); set.add(JavaLookupElementBuilder.forField(myField).withTypeText(myField.getType().getPresentableText())); - PsiField[] fields = myClass.getFields(); - for (PsiField otherField : fields) { + for (PsiField otherField : myClass.getFields()) { if (!myDefaultFieldName.equals(otherField.getName())) { PsiType otherType = otherField.getType(); - for (PsiType type : myExpectedTypes) { - if (type.equals(otherType)) { + for (SmartTypePointer pointer : myExpectedTypes) { + if (otherType.equals(pointer.getType())) { set.add(JavaLookupElementBuilder.forField(otherField).withTypeText(otherType.getPresentableText())); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/DontReportWeakerVisibilityProblemUpInHierarchy.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/DontReportWeakerVisibilityProblemUpInHierarchy.java new file mode 100644 index 000000000000..2f17edfb3e93 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/DontReportWeakerVisibilityProblemUpInHierarchy.java @@ -0,0 +1,15 @@ + +class F { + public void f() {} +} + +class E extends F { + @Override + protected void f() { + super.f(); + } +} + +class EE extends E { + +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index b1dff9c63cbb..718518b93ec4 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -467,6 +467,10 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } + public void testDontReportWeakerVisibilityProblemUpInHierarchy() throws Exception { + doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); + } + public void testJavaUtilCollections_NoVerify() throws Exception { PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule())); assertNotNull(collectionsClass); diff --git a/platform/core-impl/src/com/intellij/mock/MockApplicationEx.java b/platform/core-impl/src/com/intellij/mock/MockApplicationEx.java index 651ac40ddf22..1e7345d2826b 100644 --- a/platform/core-impl/src/com/intellij/mock/MockApplicationEx.java +++ b/platform/core-impl/src/com/intellij/mock/MockApplicationEx.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -96,6 +96,16 @@ public class MockApplicationEx extends MockApplication implements ApplicationEx return false; } + @Override + public boolean runProcessWithProgressSynchronouslyInReadAction(@Nullable Project project, + @NotNull String progressTitle, + boolean canBeCanceled, + String cancelText, + JComponent parentComponent, + @NotNull Runnable process) { + return false; + } + @NotNull @Override public T[] getExtensions(@NotNull final ExtensionPointName extensionPointName) { diff --git a/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationEx.java b/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationEx.java index 8598b505de52..5442049d0862 100644 --- a/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationEx.java +++ b/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationEx.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -65,6 +65,21 @@ public interface ApplicationEx extends Application { void doNotSave(boolean value); boolean isDoNotSave(); + /** + * Executes {@code process} in a separate thread in the application thread pool (see {@link #executeOnPooledThread(Runnable)}). + * The process is run inside read action (see {@link #runReadAction(Runnable)}) + * It is guaranteed that no other read or write action is run before the process start running. + * If the process is running for too long, a progress window shown with {@code progressTitle} and a button with {@code cancelText}. + * This method can be called from the EDT only. + * @return true if process run successfully and was not canceled. + */ + boolean runProcessWithProgressSynchronouslyInReadAction(@Nullable Project project, + @NotNull String progressTitle, + boolean canBeCanceled, + String cancelText, + JComponent parentComponent, + @NotNull Runnable process); + /** * @param force if true, no additional confirmations will be shown. The application is guaranteed to exit * @param exitConfirmed if true, suppresses any shutdown confirmation. However, if there are any background processes or tasks running, @@ -112,7 +127,7 @@ public interface ApplicationEx extends Application { void runEdtSafeAction(@NotNull Runnable runnable); /** - * Grab the lock and run the action, in a non-blocking fashion + * Tries to acquire the read lock and run the {@code action} * * @return true if action was run while holding the lock, false if was unable to get the lock and action was not run */ diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/EnterPasswordComponent.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/EnterPasswordComponent.java index 304b31e3bee1..d5f164c5108a 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/EnterPasswordComponent.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/EnterPasswordComponent.java @@ -15,7 +15,6 @@ */ package com.intellij.ide.passwordSafe.impl.providers.masterKey; -import com.intellij.ide.TypePresentationService; import com.intellij.ide.passwordSafe.HelpID; import com.intellij.openapi.ui.ValidationInfo; import com.intellij.util.ui.UIUtil; @@ -28,7 +27,7 @@ public class EnterPasswordComponent extends PasswordComponentBase { public EnterPasswordComponent(@NotNull MasterKeyPasswordSafe safe, @NotNull Class requestor) { super(safe, "Enter"); - String requestorName = TypePresentationService.getDefaultTypeName(requestor); // requestor.getSimpleName(); + String requestorName = getRequestorTitle(requestor); myPromptLabel.setText("
Master password is required to unlock the password database.
" + "The password database will be unlocked during this session
" + "for all subsystems.
" + diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyUtils.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyUtils.java deleted file mode 100644 index bd3203a4bc8f..000000000000 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyUtils.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.ide.passwordSafe.impl.providers.masterKey; - -import com.intellij.ui.DocumentAdapter; -import com.intellij.util.Processor; - -import javax.swing.*; -import javax.swing.event.DocumentEvent; -import java.util.Arrays; - -/** - * Utilities for master key provider - */ -class MasterKeyUtils { - /** - * The private constructor for utility class - */ - private MasterKeyUtils() { - } - - /** - * Match passwords - * - * @param passwordField1 the first password field - * @param passwordField2 the second password field - * @param setError the callback used to set or to clear an error - */ - static void matchPasswords(final JPasswordField passwordField1, final JPasswordField passwordField2, final Processor setError) { - DocumentAdapter l = new DocumentAdapter() { - @Override - protected void textChanged(DocumentEvent e) { - if (Arrays.equals(passwordField1.getPassword(), passwordField2.getPassword())) { - setError.process(null); - } - else { - setError.process("The new password and confirm passwords do not match."); - } - } - }; - passwordField1.getDocument().addDocumentListener(l); - passwordField2.getDocument().addDocumentListener(l); - } -} diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterPasswordDialog.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterPasswordDialog.java index f81d328c7049..f9d16b0bc63c 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterPasswordDialog.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterPasswordDialog.java @@ -63,7 +63,7 @@ public class MasterPasswordDialog extends DialogWrapper { } if (!enterMasterPasswordDialog(project, safe, requestor).showAndGet()) { - throw new MasterPasswordUnavailableException("Cancelled by user"); + throw new MasterPasswordUnavailableException(PasswordComponentBase.getRequestorTitle(requestor) + ": Cancelled by user"); } } diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/PasswordComponentBase.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/PasswordComponentBase.java index 2307fa9464f1..453fd0f133ac 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/PasswordComponentBase.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/PasswordComponentBase.java @@ -16,6 +16,7 @@ package com.intellij.ide.passwordSafe.impl.providers.masterKey; import com.intellij.icons.AllIcons; +import com.intellij.ide.TypePresentationService; import com.intellij.openapi.ui.ValidationInfo; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; @@ -100,4 +101,9 @@ public abstract class PasswordComponentBase { } return null; } + + @NotNull + public static String getRequestorTitle(@NotNull Class requestor) { + return TypePresentationService.getDefaultTypeName(requestor); + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java index b8f1e2c0b5f3..fbc4a01ebef2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java @@ -77,10 +77,7 @@ import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -644,6 +641,75 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App return !progress.isCanceled(); } + + @Override + public boolean runProcessWithProgressSynchronouslyInReadAction(@Nullable final Project project, @NotNull final String progressTitle, + final boolean canBeCanceled, + final String cancelText, final JComponent parentComponent, + @NotNull final Runnable process) { + assertIsDispatchThread(); + boolean writeAccessAllowed = isInsideWriteActionEDTOnly(); + if (writeAccessAllowed // Disallow running process in separate thread from under write action. + // The thread will deadlock trying to get read action otherwise. + ) { + throw new IncorrectOperationException("Starting process with progress from within write action makes no sense"); + } + + final ProgressWindow progress = new ProgressWindow(canBeCanceled, false, project, parentComponent, cancelText); + // in case of abrupt application exit when 'ProgressManager.getInstance().runProcess(process, progress)' below + // does not have a chance to run, and as a result the progress won't be disposed + Disposer.register(this, progress); + + progress.setTitle(progressTitle); + + final CountDownLatch readActionAcquired = new CountDownLatch(1); + final CountDownLatch modalityEntered = new CountDownLatch(1); + executeOnPooledThread(new Runnable() { + @Override + public void run() { + try { + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + readActionAcquired.countDown(); + waitFor(modalityEntered); + ProgressManager.getInstance().runProcess(process, progress); + } + }); + } + catch (ProcessCanceledException e) { + progress.cancel(); + // ok to ignore. + } + catch (RuntimeException e) { + progress.cancel(); + throw e; + } + } + }); + + waitFor(readActionAcquired); + progress.startBlocking(new Runnable() { + @Override + public void run() { + modalityEntered.countDown(); + } + }); + + LOG.assertTrue(!progress.isRunning()); + + return !progress.isCanceled(); + } + + private static void waitFor(@NotNull CountDownLatch modalityEntered) { + try { + modalityEntered.await(); + } + catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + @Override public void invokeAndWait(@NotNull Runnable runnable, @NotNull ModalityState modalityState) { Status status = getStatus(); diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java index c55b3591a5fe..e52de9913aa7 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java @@ -24,7 +24,6 @@ import com.intellij.openapi.options.ex.SortedConfigurableGroup; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.*; import com.intellij.ui.components.GradientViewport; import com.intellij.ui.treeStructure.CachingSimpleNode; @@ -34,8 +33,6 @@ import com.intellij.ui.treeStructure.SimpleTreeStructure; import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder; import com.intellij.ui.treeStructure.filtered.FilteringTreeStructure; import com.intellij.util.ArrayUtil; -import com.intellij.util.NullableFunction; -import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.ButtonlessScrollBarUI; import com.intellij.util.ui.GraphicsUtil; import com.intellij.util.ui.TextTransferable; @@ -115,24 +112,13 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd @Nullable @Override protected Transferable createTransferable(JComponent c) { - final TreePath path = myTree.getPathForRow(myTree.getLeadSelectionRow()); - if (path != null) { - final String pathInTheTree = StringUtil.join(ContainerUtil.mapNotNull(path.getPath(), new NullableFunction() { - @Nullable - @Override - public String fun(Object o) { - if (o == path.getPath()[0]) { - return null; - } - else { - final MyNode node = extractNode(o); - return node != null ? node.myDisplayName : null; - } - } - }), " | "); - if (!StringUtil.isEmpty(pathInTheTree)) { - return new TextTransferable("File | Settings | " + pathInTheTree); + MyNode node = extractNode(myTree.getPathForRow(myTree.getLeadSelectionRow())); + if (node != null) { + StringBuilder sb = new StringBuilder("File | Settings"); + for (String name : getPathNames(node)) { + sb.append(" | ").append(name); } + return new TextTransferable(sb.toString()); } return null; } @@ -206,8 +192,11 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd @NotNull String[] getPathNames(Configurable configurable) { + return getPathNames(findNode(configurable)); + } + + private static String[] getPathNames(MyNode node) { ArrayDeque path = new ArrayDeque(); - MyNode node = findNode(configurable); while (node != null) { path.push(node.myDisplayName); SimpleNode parent = node.getParent(); diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java index 510c05d06963..4cdbb8b60242 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java @@ -103,7 +103,7 @@ public class ProgressWindow extends ProgressIndicatorBase implements BlockingPro Disposer.register(this, myDialog); myFocusTrackback.registerFocusComponent(myDialog.getPanel()); - addStateDelegate(new AbstractProgressIndicatorExBase(){ + addStateDelegate(new AbstractProgressIndicatorExBase() { @Override public void cancel() { super.cancel(); @@ -186,6 +186,10 @@ public class ProgressWindow extends ProgressIndicatorBase implements BlockingPro @Override public void startBlocking() { + startBlocking(EmptyRunnable.getInstance()); + } + + public void startBlocking(@NotNull Runnable init) { ApplicationManager.getApplication().assertIsDispatchThread(); synchronized (this) { LOG.assertTrue(!isRunning()); @@ -193,6 +197,7 @@ public class ProgressWindow extends ProgressIndicatorBase implements BlockingPro } enterModality(); + init.run(); IdeEventQueue.getInstance().pumpEventsForHierarchy(myDialog.myPanel, new Condition() { @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java index 902a11e579ce..5fed8076f49f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java @@ -214,7 +214,8 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra @Deprecated public DialogWrapperPeerImpl(@NotNull DialogWrapper wrapper,final Window owner, final boolean canBeParent, final boolean applicationModalIfPossible) { - this(wrapper, owner, canBeParent, applicationModalIfPossible ? DialogWrapper.IdeModalityType.IDE : DialogWrapper.IdeModalityType.PROJECT); + this(wrapper, owner, canBeParent, + applicationModalIfPossible ? DialogWrapper.IdeModalityType.IDE : DialogWrapper.IdeModalityType.PROJECT); } @Override @@ -301,10 +302,6 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra } } - private boolean isProgressDialog() { - return myWrapper.isModalProgress(); - } - @Override @Nullable public Container getContentPane() { @@ -452,11 +449,9 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra ApplicationManager.getApplication() != null ? (CommandProcessorEx)CommandProcessor.getInstance() : null; final boolean appStarted = commandProcessor != null; - if (myDialog.isModal() && !isProgressDialog()) { - if (appStarted) { - commandProcessor.enterModal(); - LaterInvocator.enterModal(myDialog); - } + if (myDialog.isModal() && appStarted) { + commandProcessor.enterModal(); + LaterInvocator.enterModal(myDialog); } if (appStarted) { @@ -467,11 +462,9 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra myDialog.show(); } finally { - if (myDialog.isModal() && !isProgressDialog()) { - if (appStarted) { - commandProcessor.leaveModal(); - LaterInvocator.leaveModal(myDialog); - } + if (myDialog.isModal() && appStarted) { + commandProcessor.leaveModal(); + LaterInvocator.leaveModal(myDialog); } myDialog.getFocusManager().doWhenFocusSettlesDown(result.createSetDoneRunnable()); diff --git a/platform/platform-impl/src/org/jetbrains/io/JsonReaderEx.java b/platform/platform-impl/src/org/jetbrains/io/JsonReaderEx.java index a8dd68264ab6..37cf6bf7066c 100644 --- a/platform/platform-impl/src/org/jetbrains/io/JsonReaderEx.java +++ b/platform/platform-impl/src/org/jetbrains/io/JsonReaderEx.java @@ -1,3 +1,18 @@ +/* + * 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. + */ package org.jetbrains.io; import com.google.gson.JsonParseException; @@ -768,6 +783,16 @@ public final class JsonReaderEx implements Closeable { return peek() == JsonToken.STRING ? nextString() : null; } + public String nextNullableString() { + if (peek() == JsonToken.NULL) { + nextNull(); + return null; + } + else { + return nextString(); + } + } + public String nextString() { return nextString(false); } diff --git a/platform/platform-tests/testSrc/com/intellij/application/ApplicationImplTest.java b/platform/platform-tests/testSrc/com/intellij/application/ApplicationImplTest.java index 64d7f489a98f..67d0199b1f11 100644 --- a/platform/platform-tests/testSrc/com/intellij/application/ApplicationImplTest.java +++ b/platform/platform-tests/testSrc/com/intellij/application/ApplicationImplTest.java @@ -18,6 +18,7 @@ package com.intellij.application; import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ex.ApplicationEx; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; @@ -29,6 +30,7 @@ import com.intellij.testFramework.PlatformTestUtil; import com.intellij.testFramework.Timings; import com.intellij.util.ThrowableRunnable; import com.intellij.util.TimeoutUtil; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -320,4 +322,41 @@ public class ApplicationImplTest extends PlatformTestCase { thread.join(); assertNotNull(exception); } + + public void testRunProcessWithProgressSynchronouslyInReadAction() throws Throwable { + boolean result = ((ApplicationEx)ApplicationManager.getApplication()) + .runProcessWithProgressSynchronouslyInReadAction(getProject(), "title", true, "cancel", null, new Runnable() { + @Override + public void run() { + try { + assertFalse(SwingUtilities.isEventDispatchThread()); + assertTrue(ApplicationManager.getApplication().isReadAccessAllowed()); + } + catch (Throwable e) { + exception = e; + } + } + }); + assertTrue(result); + if (exception != null) throw exception; + } + + public void testRunProcessWithProgressSynchronouslyInReadActionWithPendingWriteAction() throws Throwable { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().runWriteAction(EmptyRunnable.getInstance()); + } + }); + boolean result = ((ApplicationEx)ApplicationManager.getApplication()) + .runProcessWithProgressSynchronouslyInReadAction(getProject(), "title", true, "cancel", null, new Runnable() { + @Override + public void run() { + TimeoutUtil.sleep(10000); + } + }); + assertTrue(result); + UIUtil.dispatchAllInvocationEvents(); + if (exception != null) throw exception; + } } diff --git a/platform/platform-tests/testSrc/com/intellij/util/io/HttpRequestsTest.java b/platform/platform-tests/testSrc/com/intellij/util/io/HttpRequestsTest.java index f35948816f1d..e450a3edefe1 100644 --- a/platform/platform-tests/testSrc/com/intellij/util/io/HttpRequestsTest.java +++ b/platform/platform-tests/testSrc/com/intellij/util/io/HttpRequestsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -17,13 +17,18 @@ package com.intellij.util.io; import com.intellij.ide.IdeBundle; import org.jetbrains.annotations.NotNull; +import org.junit.Before; import org.junit.Test; import java.io.IOException; +import java.net.Inet4Address; +import java.net.InetAddress; import java.net.SocketTimeoutException; import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.instanceOf; import static org.junit.Assert.*; +import static org.junit.Assume.assumeThat; public class HttpRequestsTest { private final HttpRequests.RequestProcessor myProcessor = new HttpRequests.RequestProcessor() { @@ -35,6 +40,12 @@ public class HttpRequestsTest { } }; + @Before + public void setUp() throws Exception { + InetAddress addr = InetAddress.getByName("openjdk.java.net"); + assumeThat(addr, instanceOf(Inet4Address.class)); + } + @Test public void testLimit() { try { diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/BreakpointManagerBase.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/BreakpointManagerBase.java index ef975a9508f8..f67096bea6eb 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/BreakpointManagerBase.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/BreakpointManagerBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -149,6 +149,7 @@ public abstract class BreakpointManagerBase> impleme @NotNull @Override public Promise flush(@NotNull Breakpoint breakpoint) { + //noinspection unchecked return ((T)breakpoint).flush(this); } diff --git a/platform/script-debugger/protocol/protocol-model-generator/protocol-model-generator.iml b/platform/script-debugger/protocol/protocol-model-generator/protocol-model-generator.iml index f8843ee65867..ebbedb121590 100644 --- a/platform/script-debugger/protocol/protocol-model-generator/protocol-model-generator.iml +++ b/platform/script-debugger/protocol/protocol-model-generator/protocol-model-generator.iml @@ -1,6 +1,6 @@ - + @@ -13,6 +13,8 @@ + + + - - + \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/BoxableType.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/BoxableType.java deleted file mode 100644 index 3f4b8ea839ac..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/BoxableType.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.jetbrains.protocolReader; - -abstract class BoxableType { - static final BoxableType STRING = new StandaloneType(new NamePath("String"), "writeString"); - static final BoxableType ANY_STRING = new StandaloneType(new NamePath("String"), "writeString"); - static final BoxableType INT = new StandaloneType(new NamePath("int"), "writeInt"); - static final BoxableType LONG = new StandaloneType(new NamePath("long"), "writeLong"); - static final BoxableType NUMBER = new StandaloneType(new NamePath("double"), "writeDouble"); - static final BoxableType BOOLEAN = new StandaloneType(new NamePath("boolean"), "writeBoolean"); - static final BoxableType MAP = new StandaloneType(new NamePath("java.util.Map"), "writeMap"); - - abstract CharSequence getFullText(); - - abstract String getShortText(NamePath contextNamespace); - - abstract String getWriteMethodName(); -} \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/BoxableType.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/BoxableType.kt new file mode 100644 index 000000000000..7758ea1fa8ee --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/BoxableType.kt @@ -0,0 +1,20 @@ +package org.jetbrains.protocolReader + +abstract class BoxableType { + + abstract fun getFullText(): CharSequence + + abstract fun getShortText(contextNamespace: NamePath): String + + abstract fun getWriteMethodName(): String + + default object { + val STRING: BoxableType = StandaloneType(NamePath("String"), "writeString") + val ANY_STRING: BoxableType = StandaloneType(NamePath("String"), "writeString") + val INT: BoxableType = StandaloneType(NamePath("int"), "writeInt") + val LONG: BoxableType = StandaloneType(NamePath("long"), "writeLong") + val NUMBER: BoxableType = StandaloneType(NamePath("double"), "writeDouble") + val BOOLEAN: BoxableType = StandaloneType(NamePath("boolean"), "writeBoolean") + val MAP: BoxableType = StandaloneType(NamePath("java.util.Map"), "writeMap") + } +} \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassNameScheme.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassNameScheme.java deleted file mode 100644 index 43fc7d6b0534..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassNameScheme.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.jetbrains.protocolReader; - -import org.jetbrains.annotations.NotNull; - -abstract class ClassNameScheme { - private final String suffix; - private final String rootPackage; - - private ClassNameScheme(@NotNull String suffix, String rootPackage) { - this.suffix = suffix; - this.rootPackage = rootPackage; - } - - @NotNull - NamePath getFullName(@NotNull String domainName, String baseName) { - return new NamePath(getShortName(baseName), new NamePath(getPackageNameVirtual(domainName))); - } - - @NotNull - String getShortName(@NotNull String baseName) { - return baseName.endsWith("Descriptor") ? baseName : new String(getShortNameChars(baseName)); - } - - private char[] getShortNameChars(@NotNull String baseName) { - char[] name = new char[baseName.length() + suffix.length()]; - baseName.getChars(0, baseName.length(), name, 0); - if (!suffix.isEmpty()) { - suffix.getChars(0, suffix.length(), name, baseName.length()); - } - if (Character.isLowerCase(name[0])) { - name[0] = Character.toUpperCase(name[0]); - } - if (baseName.endsWith("breakpoint")) { - name[baseName.length() - "breakpoint".length()] = 'B'; - } - else if (baseName.endsWith("breakpoints")) { - name[baseName.length() - "breakpoints".length()] = 'B'; - } - return name; - } - - protected String getPackageNameVirtual(String domainName) { - return getPackageName(rootPackage, domainName); - } - - @NotNull - public static String getPackageName(@NotNull String rootPackage, @NotNull String domain) { - if (domain.isEmpty()) { - return rootPackage; - } - return rootPackage + '.' + domain.toLowerCase(); - } - - static class Input extends ClassNameScheme { - Input(@NotNull String suffix, String rootPackage) { - super(suffix, rootPackage); - } - - String getParseMethodName(String domain, String name) { - return "read" + Generator.capitalizeFirstChar(domain) + getShortName(name); - } - } - - static class Output extends ClassNameScheme { - Output(String suffix, String rootPackage) { - super(suffix, rootPackage); - } - } - - static class Common extends ClassNameScheme { - Common(String suffix, String rootPackage) { - super(suffix, rootPackage); - } - } -} \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassNameScheme.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassNameScheme.kt new file mode 100644 index 000000000000..19e3170e1201 --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassNameScheme.kt @@ -0,0 +1,54 @@ +package org.jetbrains.protocolReader + +abstract class ClassNameScheme private(private val suffix: String, private val rootPackage: String) { + fun getFullName(domainName: String, baseName: String): NamePath { + return NamePath(getShortName(baseName), NamePath(getPackageNameVirtual(domainName))) + } + + fun getShortName(baseName: String): String { + return if (baseName.endsWith("Descriptor")) baseName else String(getShortNameChars(baseName)) + } + + private fun getShortNameChars(baseName: String): CharArray { + val name = CharArray(baseName.length() + suffix.length()) + baseName.getChars(0, baseName.length(), name, 0) + if (!suffix.isEmpty()) { + suffix.getChars(0, suffix.length(), name, baseName.length()) + } + if (Character.isLowerCase(name[0])) { + name[0] = Character.toUpperCase(name[0]) + } + if (baseName.endsWith("breakpoint")) { + name[baseName.length() - "breakpoint".length()] = 'B' + } + else if (baseName.endsWith("breakpoints")) { + name[baseName.length() - "breakpoints".length()] = 'B' + } + return name + } + + fun getPackageNameVirtual(domainName: String): String { + return getPackageName(rootPackage, domainName) + } + + class Input(suffix: String, rootPackage: String) : ClassNameScheme(suffix, rootPackage) { + + fun getParseMethodName(domain: String, name: String): String { + return "read" + Generator.capitalizeFirstChar(domain) + getShortName(name) + } + } + + class Output(suffix: String, rootPackage: String) : ClassNameScheme(suffix, rootPackage) + + class Common(suffix: String, rootPackage: String) : ClassNameScheme(suffix, rootPackage) + + default object { + + public fun getPackageName(rootPackage: String, domain: String): String { + if (domain.isEmpty()) { + return rootPackage + } + return rootPackage + '.' + domain.toLowerCase() + } + } +} \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassScope.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassScope.java deleted file mode 100644 index ccf0bee043fe..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassScope.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.jetbrains.protocolReader; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jsonProtocol.ItemDescriptor; - -import java.util.ArrayList; -import java.util.List; - -abstract class ClassScope { - private final List additionalMemberTexts = new ArrayList<>(2); - private final NamePath contextNamespace; - final DomainGenerator generator; - - ClassScope(@NotNull DomainGenerator generator, @NotNull NamePath classNamespace) { - contextNamespace = classNamespace; - this.generator = generator; - } - - protected String getShortClassName() { - return contextNamespace.getLastComponent(); - } - - NamePath getClassContextNamespace() { - return contextNamespace; - } - - void addMember(@NotNull TextOutConsumer out) { - additionalMemberTexts.add(out); - } - - void writeAdditionalMembers(@NotNull TextOutput out) { - if (additionalMemberTexts.isEmpty()) { - return; - } - - out.newLine(); - for (TextOutConsumer deferredWriter : additionalMemberTexts) { - deferredWriter.append(out); - } - } - - protected abstract TypeData.Direction getTypeDirection(); - - @NotNull - protected static String getName(@NotNull ItemDescriptor.Named named) { - return named.shortName() == null ? named.name() : named.shortName(); - } -} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassScope.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassScope.kt new file mode 100644 index 000000000000..2e0c48cd6c1e --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassScope.kt @@ -0,0 +1,30 @@ +package org.jetbrains.protocolReader + +abstract class ClassScope(val generator: DomainGenerator, val classContextNamespace: NamePath) { + private val additionalMemberTexts = ArrayList(2) + + protected fun getShortClassName(): String { + return classContextNamespace.lastComponent + } + + fun addMember(out: TextOutConsumer) { + additionalMemberTexts.add(out) + } + + fun writeAdditionalMembers(out: TextOutput) { + if (additionalMemberTexts.isEmpty()) { + return + } + + out.newLine() + for (deferredWriter in additionalMemberTexts) { + deferredWriter.append(out) + } + } + + abstract fun getTypeDirection(): TypeData.Direction + + default object { + fun getName(named: ItemDescriptor.Named) = named.shortName() ?: named.name() + } +} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/CreateStandaloneTypeBindingVisitorBase.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/CreateStandaloneTypeBindingVisitorBase.java deleted file mode 100644 index d0653004cc42..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/CreateStandaloneTypeBindingVisitorBase.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.jetbrains.protocolReader; - -import org.jetbrains.jsonProtocol.ProtocolMetaModel; - -abstract class CreateStandaloneTypeBindingVisitorBase implements TypeVisitor { - private final ProtocolMetaModel.StandaloneType type; - private final DomainGenerator generator; - - CreateStandaloneTypeBindingVisitorBase(DomainGenerator generator, ProtocolMetaModel.StandaloneType type) { - this.generator = generator; - this.type = type; - } - - protected ProtocolMetaModel.StandaloneType getType() { - return type; - } - - @Override - public StandaloneTypeBinding visitString() { - return generator.createTypedefTypeBinding(type, StandaloneTypeBinding.PredefinedTarget.STRING, generator.generator.naming.commonTypedef, null); - } - - @Override - public StandaloneTypeBinding visitInteger() { - return generator.createTypedefTypeBinding(type, StandaloneTypeBinding.PredefinedTarget.INT, generator.generator.naming.commonTypedef, null); - } - - @Override - public StandaloneTypeBinding visitRef(String refName) { - throw new RuntimeException(); - } - - @Override - public StandaloneTypeBinding visitBoolean() { - throw new RuntimeException(); - } - - @Override - public StandaloneTypeBinding visitNumber() { - return generator.createTypedefTypeBinding(type, StandaloneTypeBinding.PredefinedTarget.NUMBER, - generator.generator.naming.commonTypedef, null); - } - - @Override - public StandaloneTypeBinding visitMap() { - return generator.createTypedefTypeBinding(type, StandaloneTypeBinding.PredefinedTarget.MAP, - generator.generator.naming.commonTypedef, null); - } - - @Override - public StandaloneTypeBinding visitUnknown() { - throw new RuntimeException(); - } -} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/CreateStandaloneTypeBindingVisitorBase.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/CreateStandaloneTypeBindingVisitorBase.kt new file mode 100644 index 000000000000..dbe0f87e7da7 --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/CreateStandaloneTypeBindingVisitorBase.kt @@ -0,0 +1,32 @@ +package org.jetbrains.protocolReader + +abstract class CreateStandaloneTypeBindingVisitorBase(private val generator: DomainGenerator, protected val type: ProtocolMetaModel.StandaloneType) : TypeVisitor { + + override fun visitString(): StandaloneTypeBinding { + return generator.createTypedefTypeBinding(type, StandaloneTypeBinding.PredefinedTarget.STRING, generator.generator.naming.commonTypedef, null) + } + + override fun visitInteger(): StandaloneTypeBinding { + return generator.createTypedefTypeBinding(type, StandaloneTypeBinding.PredefinedTarget.INT, generator.generator.naming.commonTypedef, null) + } + + override fun visitRef(refName: String): StandaloneTypeBinding { + throw RuntimeException() + } + + override fun visitBoolean(): StandaloneTypeBinding { + throw RuntimeException() + } + + override fun visitNumber(): StandaloneTypeBinding { + return generator.createTypedefTypeBinding(type, StandaloneTypeBinding.PredefinedTarget.NUMBER, generator.generator.naming.commonTypedef, null) + } + + override fun visitMap(): StandaloneTypeBinding { + return generator.createTypedefTypeBinding(type, StandaloneTypeBinding.PredefinedTarget.MAP, generator.generator.naming.commonTypedef, null) + } + + override fun visitUnknown(): StandaloneTypeBinding { + throw RuntimeException() + } +} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/DomainGenerator.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/DomainGenerator.java deleted file mode 100644 index 92775a1c6393..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/DomainGenerator.java +++ /dev/null @@ -1,394 +0,0 @@ -package org.jetbrains.protocolReader; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jsonProtocol.ItemDescriptor; -import org.jetbrains.jsonProtocol.ProtocolMetaModel; - -import java.io.IOException; -import java.util.List; - -class DomainGenerator { - final ProtocolMetaModel.Domain domain; - final Generator generator; - - DomainGenerator(Generator generator, ProtocolMetaModel.Domain domain) { - this.generator = generator; - this.domain = domain; - } - - void registerTypes() { - if (domain.types() != null) { - for (ProtocolMetaModel.StandaloneType type : domain.types()) { - generator.typeMap.getTypeData(domain.domain(), type.id()).setType(type); - } - } - } - - @NotNull - static String fixMethodName(@NotNull String name) { - int i = name.indexOf("breakpoint"); - return i > 0 ? name.substring(0, i) + 'B' + name.substring(i + 1) : name; - } - - void generateCommandsAndEvents() throws IOException { - FileUpdater requestsFileUpdater = generator.startJavaFile(generator.naming.params.getPackageNameVirtual(domain.domain()), "Requests.java"); - TextOutput out = requestsFileUpdater.out; - out.append("import org.jetbrains.annotations.NotNull;").newLine(); - out.append("import org.jetbrains.jsonProtocol.Request;").newLine(); - out.newLine().append("public final class ").append("Requests"); - out.openBlock(); - - boolean isFirst = true; - - for (ProtocolMetaModel.Command command : domain.commands()) { - boolean hasResponse = command.returns() != null; - - boolean onlyMandatoryParams = true; - List params = command.parameters(); - boolean hasParams = params != null && !params.isEmpty(); - if (hasParams) { - for (ProtocolMetaModel.Parameter parameter : params) { - if (parameter.optional()) { - onlyMandatoryParams = false; - } - } - } - - String returnType = hasResponse ? generator.naming.commandResult.getShortName(command.name()) : "Void"; - if (onlyMandatoryParams) { - if (isFirst) { - isFirst = false; - } - else { - out.newLine().newLine(); - } - out.append("@NotNull").newLine().append("public static Request<"); - out.append(returnType); - out.append(">").space().append(fixMethodName(command.name())).append("("); - - OutputClassScope classScope = new OutputClassScope(this, generator.naming.params.getFullName(domain.domain(), command.name())); - BoxableType[] parameterTypes = hasParams ? new BoxableType[params.size()] : null; - if (hasParams) { - classScope.writeMethodParameters(out, params, parameterTypes); - } - - out.append(')').openBlock(); - - if (hasParams) { - out.append("V8SimpleRequest<").append(returnType).append(">").append(" r ="); - } - else { - out.append("return"); - } - - out.append(" new V8SimpleRequest<").append(returnType).append(">(\""); - if (!domain.domain().isEmpty()) { - out.append(domain.domain()).append('.'); - } - out.append(command.name()).append("\")").semi(); - - if (hasParams) { - classScope.writeWriteCalls(out, params, parameterTypes, "r"); - out.newLine().append("return r").semi(); - } - - out.closeBlock(); - } - else { - generateRequest(command, returnType); - } - - if (hasResponse) { - FileUpdater fileUpdater = generator.startJavaFile(generator.naming.commandResult, domain, command.name()); - generateJsonProtocolInterface(fileUpdater.out, generator.naming.commandResult.getShortName(command.name()), command.description(), command.returns(), null); - fileUpdater.update(); - generator.jsonProtocolParserClassNames.add(generator.naming.commandResult.getFullName(domain.domain(), command.name()).getFullText()); - generator.parserRootInterfaceItems.add(new ParserRootInterfaceItem(domain.domain(), command.name(), generator.naming.commandResult)); - } - } - - out.closeBlock(); - requestsFileUpdater.update(); - - if (domain.events() != null) { - for (ProtocolMetaModel.Event event : domain.events()) { - generateEvenData(event); - generator.jsonProtocolParserClassNames.add(generator.naming.eventData.getFullName(domain.domain(), event.name()).getFullText()); - generator.parserRootInterfaceItems.add(new ParserRootInterfaceItem(domain.domain(), event.name(), generator.naming.eventData)); - } - } - } - - private void generateRequest(@NotNull final ProtocolMetaModel.Command command, @NotNull final String returnType) throws IOException { - TextOutConsumer baseTypeBuilder = new TextOutConsumer() { - @Override - public void append(TextOutput out) { - out.space().append("extends ").append(generator.naming.requestClassName).append('<').append(returnType).append('>'); - } - }; - - TextOutConsumer memberBuilder = new TextOutConsumer() { - @Override - public void append(TextOutput out) { - out.append("@NotNull").newLine().append("@Override").newLine().append("public String getMethodName()").openBlock(); - out.append("return \""); - if (!domain.domain().isEmpty()) { - out.append(domain.domain()).append('.'); - } - out.append(command.name()).append("\";").closeBlock(); - } - }; - generateTopLevelOutputClass(generator.naming.params, command.name(), command.description(), baseTypeBuilder, - memberBuilder, command.parameters()); - } - - void generateCommandAdditionalParam(ProtocolMetaModel.StandaloneType type) throws IOException { - generateTopLevelOutputClass(generator.naming.additionalParam, type.id(), type.description(), null, null, type.properties()); - } - - private

void generateTopLevelOutputClass(@NotNull ClassNameScheme nameScheme, - String baseName, - String description, - @Nullable TextOutConsumer baseType, - @Nullable TextOutConsumer additionalMemberText, - List

properties) throws IOException { - FileUpdater fileUpdater = generator.startJavaFile(nameScheme, domain, baseName); - if (nameScheme == generator.naming.params) { - fileUpdater.out.append("import org.jetbrains.annotations.NotNull;").newLine().newLine(); - } - generateOutputClass(fileUpdater.out, nameScheme.getFullName(domain.domain(), baseName), description, baseType, additionalMemberText, properties); - fileUpdater.update(); - } - - private

void generateOutputClass(@NotNull TextOutput out, - NamePath classNamePath, - String description, - @Nullable TextOutConsumer baseType, - TextOutConsumer additionalMemberText, - List

properties) { - out.doc(description); - out.append("public final class ").append(classNamePath.getLastComponent()); - if (baseType == null) { - out.append(" extends ").append("org.jetbrains.jsonProtocol.OutMessage"); - } - else { - baseType.append(out); - } - - OutputClassScope classScope = new OutputClassScope(this, classNamePath); - if (additionalMemberText != null) { - classScope.addMember(additionalMemberText); - } - - out.openBlock(); - classScope.generate(out, properties); - classScope.writeAdditionalMembers(out); - out.closeBlock(); - } - - StandaloneTypeBinding createStandaloneOutputTypeBinding(@NotNull ProtocolMetaModel.StandaloneType type, @NotNull String name) { - return Generator.switchByType(type, new MyCreateStandaloneTypeBindingVisitorBase(this, type, name)); - } - - StandaloneTypeBinding createStandaloneInputTypeBinding(ProtocolMetaModel.StandaloneType type) { - return Generator.switchByType(type, new CreateStandaloneTypeBindingVisitorBase(this, type) { - @Override - public StandaloneTypeBinding visitObject(List properties) { - return createStandaloneObjectInputTypeBinding(getType(), properties); - } - - @Override - public StandaloneTypeBinding visitEnum(List enumConstants) { - return createStandaloneEnumInputTypeBinding(getType(), enumConstants, - TypeData.Direction.INPUT); - } - - @Override - public StandaloneTypeBinding visitArray(ProtocolMetaModel.ArrayItemType items) { - ResolveAndGenerateScope resolveAndGenerateScope = new ResolveAndGenerateScope() { - // This class is responsible for generating ad hoc type. - // If we ever are to do it, we should generate into string buffer and put strings - // inside TypeDef class. - @Override - public String getDomainName() { - return domain.domain(); - } - - @Override - public TypeData.Direction getTypeDirection() { - return TypeData.Direction.INPUT; - } - - @Override - public TypeDescriptor resolveType(T typedObject) { - throw new UnsupportedOperationException(); - } - - @Override - public BoxableType generateNestedObject(String description, List properties) { - throw new UnsupportedOperationException(); - } - }; - BoxableType itemBoxableType = generator.resolveType(items, resolveAndGenerateScope).getType(); - - final BoxableType arrayType = new ListType(itemBoxableType); - StandaloneTypeBinding.Target target = new StandaloneTypeBinding.Target() { - @Override - public BoxableType resolve(ResolveContext context) { - return arrayType; - } - }; - - return createTypedefTypeBinding(getType(), target, generator.naming.inputTypedef, TypeData.Direction.INPUT); - } - }); - } - - StandaloneTypeBinding createStandaloneObjectInputTypeBinding(@NotNull final ProtocolMetaModel.StandaloneType type, @Nullable final List properties) { - final String name = type.id(); - final NamePath fullTypeName = generator.naming.inputValue.getFullName(domain.domain(), name); - generator.jsonProtocolParserClassNames.add(fullTypeName.getFullText()); - - return new StandaloneTypeBinding() { - @Override - public BoxableType getJavaType() { - return new StandaloneType(fullTypeName, "writeMessage"); - } - - @Override - public void generate() throws IOException { - NamePath className = generator.naming.inputValue.getFullName(domain.domain(), name); - FileUpdater fileUpdater = generator.startJavaFile(generator.naming.inputValue, domain, name); - TextOutput out = fileUpdater.out; - if (type.description() != null) { - out.doc(type.description()); - } - - out.append("@org.jetbrains.jsonProtocol.JsonType").newLine(); - out.append("public interface ").append(className.getLastComponent()).openBlock(); - InputClassScope classScope = new InputClassScope(DomainGenerator.this, className); - if (properties != null) { - classScope.generateDeclarationBody(out, properties); - } - classScope.writeAdditionalMembers(out); - out.closeBlock(); - fileUpdater.update(); - } - - @Override public TypeData.Direction getDirection() { - return TypeData.Direction.INPUT; - } - }; - } - - StandaloneTypeBinding createStandaloneEnumInputTypeBinding(final ProtocolMetaModel.StandaloneType type, - final List enumConstants, final TypeData.Direction direction) { - final String name = type.id(); - return new StandaloneTypeBinding() { - @Override - public BoxableType getJavaType() { - return new StandaloneType(generator.naming.inputEnum.getFullName(domain.domain(), name), "writeEnum"); - } - - @Override - public void generate() throws IOException { - FileUpdater fileUpdater = generator.startJavaFile(generator.naming.inputEnum, domain, name); - fileUpdater.out.doc(type.description()); - Enums.appendEnums(enumConstants, generator.naming.inputEnum.getShortName(name), true, fileUpdater.out); - fileUpdater.update(); - } - - @Override - public TypeData.Direction getDirection() { - return direction; - } - }; - } - - /** - * Typedef is an empty class that just holds description and - * refers to an actual type (such as String). - */ - StandaloneTypeBinding createTypedefTypeBinding(final ProtocolMetaModel.StandaloneType type, StandaloneTypeBinding.Target target, - final ClassNameScheme nameScheme, final TypeData.Direction direction) { - final String name = type.id(); - final NamePath typedefJavaName = nameScheme.getFullName(domain.domain(), name); - final BoxableType actualJavaType = target.resolve(new StandaloneTypeBinding.Target.ResolveContext() { - @Override - public BoxableType generateNestedObject(String shortName, String description, List properties) { - NamePath classNamePath = new NamePath(shortName, typedefJavaName); - if (direction == null) { - throw new RuntimeException("Unsupported"); - } - - switch (direction) { - case INPUT: - throw new RuntimeException("TODO"); - case OUTPUT: - TextOutput out = new TextOutput(new StringBuilder()); - generateOutputClass(out, classNamePath, description, null, null, properties); - break; - default: - throw new RuntimeException(); - } - return new StandaloneType(new NamePath(shortName, typedefJavaName), "writeMessage"); - } - }); - - return new StandaloneTypeBinding() { - @Override - public BoxableType getJavaType() { - return actualJavaType; - } - - @Override - public void generate() { - } - - @Override - public TypeData.Direction getDirection() { - return direction; - } - }; - } - - private void generateEvenData(final ProtocolMetaModel.Event event) throws IOException { - String className = generator.naming.eventData.getShortName(event.name()); - FileUpdater fileUpdater = generator.startJavaFile(generator.naming.eventData, domain, event.name()); - final String domainName = domain.domain(); - final CharSequence fullName = generator.naming.eventData.getFullName(domainName, event.name()).getFullText(); - generateJsonProtocolInterface(fileUpdater.out, className, event.description(), event.parameters(), new TextOutConsumer() { - @Override - public void append(TextOutput out) { - out.newLine().append("org.jetbrains.wip.protocol.WipEventType<").append(fullName).append("> TYPE").newLine(); - out.append("\t= new org.jetbrains.wip.protocol.WipEventType<").append(fullName).append(">"); - out.append("(\"").append(domainName).append('.').append(event.name()).append("\", ").append(fullName).append(".class)").openBlock(); - { - out.append("@Override").newLine().append("public ").append(fullName).append(" read("); - out.append(generator.naming.inputPackage).append('.').append(Generator.READER_INTERFACE_NAME + " protocolReader, ").append(Util.JSON_READER_PARAMETER_DEF).append(")").openBlock(); - out.append("return protocolReader.").append(generator.naming.eventData.getParseMethodName(domainName, event.name())).append("(reader);").closeBlock(); - } - out.closeBlock(); - out.semi(); - } - }); - fileUpdater.update(); - } - - private void generateJsonProtocolInterface(TextOutput out, String className, String description, List parameters, TextOutConsumer additionalMembersText) { - if (description != null) { - out.doc(description); - } - out.append("@org.jetbrains.jsonProtocol.JsonType").newLine().append("public interface ").append(className).openBlock(); - InputClassScope classScope = new InputClassScope(this, new NamePath(className, new NamePath(ClassNameScheme.getPackageName(generator.naming.inputPackage, domain.domain())))); - if (additionalMembersText != null) { - classScope.addMember(additionalMembersText); - } - if (parameters != null) { - classScope.generateDeclarationBody(out, parameters); - } - classScope.writeAdditionalMembers(out); - out.closeBlock(); - } -} \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/DomainGenerator.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/DomainGenerator.kt new file mode 100644 index 000000000000..4b45aa5edbaa --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/DomainGenerator.kt @@ -0,0 +1,348 @@ +package org.jetbrains.protocolReader + +class DomainGenerator(val generator: Generator, val domain: ProtocolMetaModel.Domain) { + + fun registerTypes() { + if (domain.types() != null) { + for (type in domain.types()!!) { + generator.typeMap.getTypeData(domain.domain(), type.id()).setType(type) + } + } + } + + throws(javaClass()) + fun generateCommandsAndEvents() { + val requestsFileUpdater = generator.startJavaFile(generator.naming.params.getPackageNameVirtual(domain.domain()), "Requests.java") + val out = requestsFileUpdater.out + out.append("import org.jetbrains.annotations.NotNull;").newLine() + out.append("import org.jetbrains.jsonProtocol.Request;").newLine() + out.newLine().append("public final class ").append("Requests") + out.openBlock() + + var isFirst = true + + for (command in domain.commands()) { + val hasResponse = command.returns() != null + + var onlyMandatoryParams = true + val params = command.parameters() + val hasParams = params != null && !params.isEmpty() + if (hasParams) { + for (parameter in params!!) { + if (parameter.optional()) { + onlyMandatoryParams = false + } + } + } + + val returnType = if (hasResponse) generator.naming.commandResult.getShortName(command.name()) else "Void" + if (onlyMandatoryParams) { + if (isFirst) { + isFirst = false + } + else { + out.newLine().newLine() + } + out.append("@NotNull").newLine().append("public static Request<") + out.append(returnType) + out.append(">").space().append(fixMethodName(command.name())).append("(") + + val classScope = OutputClassScope(this, generator.naming.params.getFullName(domain.domain(), command.name())) + val parameterTypes = if (hasParams) arrayOfNulls(params!!.size()) else null + if (hasParams) { + classScope.writeMethodParameters(out, params!!, parameterTypes!!) + } + + out.append(')').openBlock() + + if (hasParams) { + out.append("V8SimpleRequest<").append(returnType).append(">").append(" r =") + } + else { + out.append("return") + } + + out.append(" new V8SimpleRequest<").append(returnType).append(">(\"") + if (!domain.domain().isEmpty()) { + out.append(domain.domain()).append('.') + } + out.append(command.name()).append("\")").semi() + + if (hasParams) { + classScope.writeWriteCalls(out, params!!, parameterTypes!!, "r") + out.newLine().append("return r").semi() + } + + out.closeBlock() + } + else { + generateRequest(command, returnType) + } + + if (hasResponse) { + val fileUpdater = generator.startJavaFile(generator.naming.commandResult, domain, command.name()) + generateJsonProtocolInterface(fileUpdater.out, generator.naming.commandResult.getShortName(command.name()), command.description(), command.returns(), null) + fileUpdater.update() + generator.jsonProtocolParserClassNames.add(generator.naming.commandResult.getFullName(domain.domain(), command.name()).getFullText()) + generator.parserRootInterfaceItems.add(ParserRootInterfaceItem(domain.domain(), command.name(), generator.naming.commandResult)) + } + } + + out.closeBlock() + requestsFileUpdater.update() + + if (domain.events() != null) { + for (event in domain.events()!!) { + generateEvenData(event) + generator.jsonProtocolParserClassNames.add(generator.naming.eventData.getFullName(domain.domain(), event.name()).getFullText()) + generator.parserRootInterfaceItems.add(ParserRootInterfaceItem(domain.domain(), event.name(), generator.naming.eventData)) + } + } + } + + throws(javaClass()) + private fun generateRequest(command: ProtocolMetaModel.Command, returnType: String) { + val baseTypeBuilder = object : TextOutConsumer { + override fun append(out: TextOutput) { + out.space().append("extends ").append(generator.naming.requestClassName).append('<').append(returnType).append('>') + } + } + + val memberBuilder = object : TextOutConsumer { + override fun append(out: TextOutput) { + out.append("@NotNull").newLine().append("@Override").newLine().append("public String getMethodName()").openBlock() + out.append("return \"") + if (!domain.domain().isEmpty()) { + out.append(domain.domain()).append('.') + } + out.append(command.name()).append("\";").closeBlock() + } + } + generateTopLevelOutputClass(generator.naming.params, command.name(), command.description(), baseTypeBuilder, memberBuilder, command.parameters()) + } + + fun generateCommandAdditionalParam(type: ProtocolMetaModel.StandaloneType) { + generateTopLevelOutputClass(generator.naming.additionalParam, type.id(), type.description(), null, null, type.properties()) + } + + private fun

generateTopLevelOutputClass(nameScheme: ClassNameScheme, baseName: String, description: String?, baseType: TextOutConsumer?, additionalMemberText: TextOutConsumer?, properties: List

?) { + val fileUpdater = generator.startJavaFile(nameScheme, domain, baseName) + if (nameScheme == generator.naming.params) { + fileUpdater.out.append("import org.jetbrains.annotations.NotNull;").newLine().newLine() + } + generateOutputClass(fileUpdater.out, nameScheme.getFullName(domain.domain(), baseName), description, baseType, additionalMemberText, properties) + fileUpdater.update() + } + + private fun

generateOutputClass(out: TextOutput, classNamePath: NamePath, description: String?, baseType: TextOutConsumer?, additionalMemberText: TextOutConsumer?, properties: List

?) { + out.doc(description) + out.append("public final class ").append(classNamePath.lastComponent) + if (baseType == null) { + out.append(" extends ").append("org.jetbrains.jsonProtocol.OutMessage") + } + else { + baseType.append(out) + } + + val classScope = OutputClassScope(this, classNamePath) + if (additionalMemberText != null) { + classScope.addMember(additionalMemberText) + } + + out.openBlock() + classScope.generate

(out, properties) + classScope.writeAdditionalMembers(out) + out.closeBlock() + } + + fun createStandaloneOutputTypeBinding(type: ProtocolMetaModel.StandaloneType, name: String): StandaloneTypeBinding { + return Generator.switchByType(type, MyCreateStandaloneTypeBindingVisitorBase(this, type, name)) + } + + fun createStandaloneInputTypeBinding(type: ProtocolMetaModel.StandaloneType): StandaloneTypeBinding { + return Generator.switchByType(type, object : CreateStandaloneTypeBindingVisitorBase(this, type) { + override fun visitObject(properties: List?): StandaloneTypeBinding { + return createStandaloneObjectInputTypeBinding(type, properties) + } + + override fun visitEnum(enumConstants: List): StandaloneTypeBinding { + return createStandaloneEnumInputTypeBinding(type, enumConstants, TypeData.Direction.INPUT) + } + + override fun visitArray(items: ProtocolMetaModel.ArrayItemType): StandaloneTypeBinding { + val resolveAndGenerateScope = object : ResolveAndGenerateScope { + // This class is responsible for generating ad hoc type. + // If we ever are to do it, we should generate into string buffer and put strings + // inside TypeDef class. + override fun getDomainName(): String { + return domain.domain() + } + + override fun getTypeDirection(): TypeData.Direction { + return TypeData.Direction.INPUT + } + + override fun resolveType(typedObject: T): TypeDescriptor { + throw UnsupportedOperationException() + } + + override fun generateNestedObject(description: String?, properties: List?) = throw UnsupportedOperationException() + } + val itemBoxableType = generator.resolveType(items, resolveAndGenerateScope).type + + val arrayType = ListType(itemBoxableType) + val target = object : StandaloneTypeBinding.Target { + override fun resolve(context: StandaloneTypeBinding.Target.ResolveContext): BoxableType { + return arrayType + } + } + + return createTypedefTypeBinding(type, target, generator.naming.inputTypedef, TypeData.Direction.INPUT) + } + }) + } + + fun createStandaloneObjectInputTypeBinding(type: ProtocolMetaModel.StandaloneType, properties: List?): StandaloneTypeBinding { + val name = type.id() + val fullTypeName = generator.naming.inputValue.getFullName(domain.domain(), name) + generator.jsonProtocolParserClassNames.add(fullTypeName.getFullText()) + + return object : StandaloneTypeBinding { + override fun getJavaType(): BoxableType { + return StandaloneType(fullTypeName, "writeMessage") + } + + throws(javaClass()) + override fun generate() { + val className = generator.naming.inputValue.getFullName(domain.domain(), name) + val fileUpdater = generator.startJavaFile(generator.naming.inputValue, domain, name) + val out = fileUpdater.out + if (type.description() != null) { + out.doc(type.description()) + } + + out.append("@org.jetbrains.jsonProtocol.JsonType").newLine() + out.append("public interface ").append(className.lastComponent).openBlock() + val classScope = InputClassScope(this@DomainGenerator, className) + if (properties != null) { + classScope.generateDeclarationBody(out, properties) + } + classScope.writeAdditionalMembers(out) + out.closeBlock() + fileUpdater.update() + } + + override fun getDirection(): TypeData.Direction? { + return TypeData.Direction.INPUT + } + } + } + + fun createStandaloneEnumInputTypeBinding(type: ProtocolMetaModel.StandaloneType, enumConstants: List, direction: TypeData.Direction): StandaloneTypeBinding { + val name = type.id() + return object : StandaloneTypeBinding { + override fun getJavaType(): BoxableType { + return StandaloneType(generator.naming.inputEnum.getFullName(domain.domain(), name), "writeEnum") + } + + throws(javaClass()) + override fun generate() { + val fileUpdater = generator.startJavaFile(generator.naming.inputEnum, domain, name) + fileUpdater.out.doc(type.description()) + Enums.appendEnums(enumConstants, generator.naming.inputEnum.getShortName(name), true, fileUpdater.out) + fileUpdater.update() + } + + override fun getDirection(): TypeData.Direction? { + return direction + } + } + } + + /** + * Typedef is an empty class that just holds description and + * refers to an actual type (such as String). + */ + fun createTypedefTypeBinding(type: ProtocolMetaModel.StandaloneType, target: StandaloneTypeBinding.Target, nameScheme: ClassNameScheme, direction: TypeData.Direction?): StandaloneTypeBinding { + val name = type.id() + val typedefJavaName = nameScheme.getFullName(domain.domain(), name) + val actualJavaType = target.resolve(object : StandaloneTypeBinding.Target.ResolveContext { + override fun generateNestedObject(shortName: String, description: String?, properties: List?): BoxableType { + val classNamePath = NamePath(shortName, typedefJavaName) + if (direction == null) { + throw RuntimeException("Unsupported") + } + + when (direction) { + TypeData.Direction.INPUT -> throw RuntimeException("TODO") + TypeData.Direction.OUTPUT -> { + val out = TextOutput(StringBuilder()) + generateOutputClass(out, classNamePath, description, null, null, properties) + } + else -> throw RuntimeException() + } + return StandaloneType(NamePath(shortName, typedefJavaName), "writeMessage") + } + }) + + return object : StandaloneTypeBinding { + override fun getJavaType(): BoxableType { + return actualJavaType + } + + override fun generate() { + } + + override fun getDirection(): TypeData.Direction? { + return direction + } + } + } + + throws(javaClass()) + private fun generateEvenData(event: ProtocolMetaModel.Event) { + val className = generator.naming.eventData.getShortName(event.name()) + val fileUpdater = generator.startJavaFile(generator.naming.eventData, domain, event.name()) + val domainName = domain.domain() + val fullName = generator.naming.eventData.getFullName(domainName, event.name()).getFullText() + generateJsonProtocolInterface(fileUpdater.out, className, event.description(), event.parameters(), object : TextOutConsumer { + override fun append(out: TextOutput) { + out.newLine().append("org.jetbrains.wip.protocol.WipEventType<").append(fullName).append("> TYPE").newLine() + out.append("\t= new org.jetbrains.wip.protocol.WipEventType<").append(fullName).append(">") + out.append("(\"").append(domainName).append('.').append(event.name()).append("\", ").append(fullName).append(".class)").openBlock() + run { + out.append("@Override").newLine().append("public ").append(fullName).append(" read(") + out.append(generator.naming.inputPackage).append('.').append(Generator.READER_INTERFACE_NAME + " protocolReader, ").append(JSON_READER_PARAMETER_DEF).append(")").openBlock() + out.append("return protocolReader.").append(generator.naming.eventData.getParseMethodName(domainName, event.name())).append("(reader);").closeBlock() + } + out.closeBlock() + out.semi() + } + }) + fileUpdater.update() + } + + private fun generateJsonProtocolInterface(out: TextOutput, className: String, description: String?, parameters: List?, additionalMembersText: TextOutConsumer?) { + if (description != null) { + out.doc(description) + } + out.append("@org.jetbrains.jsonProtocol.JsonType").newLine().append("public interface ").append(className).openBlock() + val classScope = InputClassScope(this, NamePath(className, NamePath(ClassNameScheme.getPackageName(generator.naming.inputPackage, domain.domain())))) + if (additionalMembersText != null) { + classScope.addMember(additionalMembersText) + } + if (parameters != null) { + classScope.generateDeclarationBody(out, parameters) + } + classScope.writeAdditionalMembers(out) + out.closeBlock() + } + + default object { + + fun fixMethodName(name: String): String { + val i = name.indexOf("breakpoint") + return if (i > 0) name.substring(0, i) + 'B' + name.substring(i + 1) else name + } + } +} \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/FileSet.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/FileSet.java deleted file mode 100644 index b6a79b6176c7..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/FileSet.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.jetbrains.protocolReader; - -import gnu.trove.THashSet; -import gnu.trove.TObjectProcedure; -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; -import java.nio.file.*; -import java.nio.file.attribute.BasicFileAttributes; - -/** - * Records a list of files in the root directory and deletes files that were not re-generated. - */ -class FileSet { - private final Path rootDir; - @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") - private final THashSet unusedFiles; - - FileSet(Path rootDir) throws IOException { - this.rootDir = rootDir; - unusedFiles = new THashSet(); - Files.walkFileTree(rootDir, new SimpleFileVisitor() { - @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { - return Files.isHidden(dir) ? FileVisitResult.SKIP_SUBTREE : FileVisitResult.CONTINUE; - } - - @NotNull - @Override - public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException { - if (!Files.isHidden(path)) { - unusedFiles.add(path); - } - return FileVisitResult.CONTINUE; - } - }); - } - - FileUpdater createFileUpdater(String filePath) { - Path file = rootDir.resolve(filePath); - unusedFiles.remove(file); - return new FileUpdater(file); - } - - void deleteOtherFiles() { - unusedFiles.forEach(new TObjectProcedure() { - @Override - public boolean execute(Path path) { - try { - if (Files.deleteIfExists(path)) { - Path parent = path.getParent(); - try (DirectoryStream stream = Files.newDirectoryStream(parent)) { - if (!stream.iterator().hasNext()) { - Files.delete(parent); - } - } - } - } - catch (IOException e) { - throw new RuntimeException(e); - } - return true; - } - }); - } -} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/FileSet.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/FileSet.kt new file mode 100644 index 000000000000..74eb02b23a41 --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/FileSet.kt @@ -0,0 +1,56 @@ +package org.jetbrains.protocolReader + +/** + * Records a list of files in the root directory and deletes files that were not re-generated. + */ +class FileSet [throws(javaClass())] +(private val rootDir: Path) { + SuppressWarnings("MismatchedQueryAndUpdateOfCollection") + private val unusedFiles: THashSet + + { + unusedFiles = THashSet() + Files.walkFileTree(rootDir, object : SimpleFileVisitor() { + throws(javaClass()) + override fun preVisitDirectory(dir: Path, attrs: BasicFileAttributes): FileVisitResult { + return if (Files.isHidden(dir)) FileVisitResult.SKIP_SUBTREE else FileVisitResult.CONTINUE + } + + throws(javaClass()) + override fun visitFile(path: Path, attrs: BasicFileAttributes): FileVisitResult { + if (!Files.isHidden(path)) { + unusedFiles.add(path) + } + return FileVisitResult.CONTINUE + } + }) + } + + fun createFileUpdater(filePath: String): FileUpdater { + val file = rootDir.resolve(filePath) + unusedFiles.remove(file) + return FileUpdater(file) + } + + fun deleteOtherFiles() { + unusedFiles.forEach(object : TObjectProcedure { + override fun execute(path: Path): Boolean { + try { + if (Files.deleteIfExists(path)) { + val parent = path.getParent() + Files.newDirectoryStream(parent).use { stream -> + if (!stream.iterator().hasNext()) { + Files.delete(parent) + } + } + } + } + catch (e: IOException) { + throw RuntimeException(e) + } + + return true + } + }) + } +} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.java deleted file mode 100644 index abd58b0a8c6e..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.java +++ /dev/null @@ -1,314 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.jetbrains.protocolReader; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jsonProtocol.ItemDescriptor; - -import java.io.IOException; -import java.nio.file.FileSystems; -import java.util.*; - -import static org.jetbrains.jsonProtocol.ProtocolMetaModel.*; - -/** - * Read metamodel and generates set of files with Java classes/interfaces for the protocol. - */ -class Generator { - private static final String PARSER_INTERFACE_LIST_CLASS_NAME = "GeneratedReaderInterfaceList"; - static final String READER_INTERFACE_NAME = "ProtocolResponseReader"; - - final List jsonProtocolParserClassNames = new ArrayList<>(); - final List parserRootInterfaceItems = new ArrayList<>(); - final TypeMap typeMap = new TypeMap(); - - private final FileSet fileSet; - final Naming naming; - - Generator(String outputDir, String rootPackage, String requestClassName) throws IOException { - fileSet = new FileSet(FileSystems.getDefault().getPath(outputDir)); - naming = new Naming(rootPackage, requestClassName); - } - - public static final class Naming { - public final ClassNameScheme params; - public final ClassNameScheme additionalParam; - public final ClassNameScheme outputTypedef; - - public final ClassNameScheme.Input commandResult; - public final ClassNameScheme.Input eventData; - public final ClassNameScheme inputValue; - public final ClassNameScheme inputEnum; - public final ClassNameScheme inputTypedef; - - public final ClassNameScheme commonTypedef; - - public final String inputPackage; - public final String requestClassName; - - private Naming(String rootPackage, String requestClassName) { - this.requestClassName = requestClassName; - - params = new ClassNameScheme.Output("", rootPackage); - additionalParam = new ClassNameScheme.Output("", rootPackage); - outputTypedef = new ClassNameScheme.Output("Typedef", rootPackage); - commonTypedef = new ClassNameScheme.Common("Typedef", rootPackage); - - inputPackage = rootPackage; - commandResult = new ClassNameScheme.Input("Result", inputPackage); - eventData = new ClassNameScheme.Input("EventData", inputPackage); - inputValue = new ClassNameScheme.Input("Value", inputPackage); - inputEnum = new ClassNameScheme.Input("", inputPackage); - inputTypedef = new ClassNameScheme.Input("Typedef", inputPackage); - } - } - - private static boolean isDomainSkipped(Domain domain) { - if (domain.domain().equals("CSS") || domain.domain().equals("Inspector")) { - return false; - } - - // todo DOMDebugger - return domain.hidden() || - domain.domain().equals("DOMDebugger") || - domain.domain().equals("Timeline") || - domain.domain().equals("Input"); - } - - void go(Root metamodel) throws IOException { - initializeKnownTypes(); - - List domainList = metamodel.domains(); - Map domainGeneratorMap = new HashMap<>(); - for (Domain domain : domainList) { - if (isDomainSkipped(domain)) { - System.out.println("Domain skipped: " + domain.domain()); - continue; - } - DomainGenerator domainGenerator = new DomainGenerator(this, domain); - domainGeneratorMap.put(domain.domain(), domainGenerator); - domainGenerator.registerTypes(); - } - - for (Domain domain : domainList) { - if (!isDomainSkipped(domain)) { - System.out.println("Domain generated: " + domain.domain()); - } - } - - typeMap.setDomainGeneratorMap(domainGeneratorMap); - - for (DomainGenerator domainGenerator : domainGeneratorMap.values()) { - domainGenerator.generateCommandsAndEvents(); - } - - typeMap.generateRequestedTypes(); - generateParserInterfaceList(); - generateParserRoot(parserRootInterfaceItems); - fileSet.deleteOtherFiles(); - } - - TypeDescriptor resolveType(@NotNull final ItemDescriptor typedObject, @NotNull final ResolveAndGenerateScope scope) { - final boolean optional = typedObject instanceof ItemDescriptor.Named && ((ItemDescriptor.Named)typedObject).optional(); - return switchByType(typedObject, new TypeVisitor() { - @Override - public TypeDescriptor visitRef(String refName) { - return new TypeDescriptor(resolveRefType(scope.getDomainName(), refName, scope.getTypeDirection()), optional); - } - - @Override - public TypeDescriptor visitBoolean() { - return new TypeDescriptor(BoxableType.BOOLEAN, optional); - } - - @Override - public TypeDescriptor visitEnum(List enumConstants) { - assert scope instanceof MemberScope; - return new TypeDescriptor(((MemberScope)scope).generateEnum(typedObject.description(), enumConstants), optional); - } - - @Override - public TypeDescriptor visitString() { - return new TypeDescriptor(BoxableType.STRING, optional); - } - - @Override - public TypeDescriptor visitInteger() { - return new TypeDescriptor(BoxableType.INT, optional); - } - - @Override - public TypeDescriptor visitNumber() { - return new TypeDescriptor(BoxableType.NUMBER, optional); - } - - @Override - public TypeDescriptor visitMap() { - return new TypeDescriptor(BoxableType.MAP, optional); - } - - @Override - public TypeDescriptor visitArray(ArrayItemType items) { - BoxableType type = scope.resolveType(items).getType(); - return new TypeDescriptor(new ListType(type), optional, false, type == BoxableType.ANY_STRING); - } - - @Override - public TypeDescriptor visitObject(List properties) { - return new TypeDescriptor(scope.generateNestedObject(typedObject.description(), properties), optional); - } - - @Override - public TypeDescriptor visitUnknown() { - return new TypeDescriptor(BoxableType.STRING, optional, false, true); - } - }); - } - - private void generateParserInterfaceList() throws IOException { - FileUpdater fileUpdater = startJavaFile(naming.inputPackage, PARSER_INTERFACE_LIST_CLASS_NAME + ".java"); - // Write classes in stable order. - Collections.sort(jsonProtocolParserClassNames); - - TextOutput out = fileUpdater.out; - out.append("public class ").append(PARSER_INTERFACE_LIST_CLASS_NAME).openBlock(); - out.append("public static final Class[] LIST =").openBlock(); - for (String name : jsonProtocolParserClassNames) { - out.append(name).append(".class,").newLine(); - } - out.closeBlock(); - out.semi(); - out.closeBlock(); - fileUpdater.update(); - } - - private void generateParserRoot(List parserRootInterfaceItems) throws IOException { - FileUpdater fileUpdater = startJavaFile(naming.inputPackage, READER_INTERFACE_NAME + ".java"); - // Write classes in stable order. - Collections.sort(parserRootInterfaceItems); - - TextOutput out = fileUpdater.out; - out.append("public abstract class ").append(READER_INTERFACE_NAME).space().append("implements org.jetbrains.jsonProtocol.ResponseResultReader").openBlock(); - for (ParserRootInterfaceItem item : parserRootInterfaceItems) { - item.writeCode(out); - } - out.newLine().newLine().append("@Override").newLine().append("public Object readResult(String methodName, org.jetbrains.io.JsonReaderEx reader)"); - out.openBlock(); - - boolean isNotFirst = false; - for (ParserRootInterfaceItem item : parserRootInterfaceItems) { - if (isNotFirst) { - out.append("else "); - } - else { - isNotFirst = true; - } - out.append("if (methodName.equals(\""); - if (!item.domain.isEmpty()) { - out.append(item.domain).append('.'); - } - out.append(item.name).append('"').append(")) return "); - item.appendReadMethodName(out); - out.append("(reader)").semi().newLine(); - } - out.append("else return null").semi(); - out.closeBlock(); - - out.closeBlock(); - fileUpdater.update(); - } - - /** - * Resolve absolute (DOMAIN.TYPE) or relative (TYPE) type name - */ - private BoxableType resolveRefType(String scopeDomainName, String refName, - TypeData.Direction direction) { - int pos = refName.indexOf('.'); - String domainName; - String shortName; - if (pos == -1) { - domainName = scopeDomainName; - shortName = refName; - } - else { - domainName = refName.substring(0, pos); - shortName = refName.substring(pos + 1); - } - return typeMap.resolve(domainName, shortName, direction); - } - - static String generateMethodNameSubstitute(@NotNull String originalName, @NotNull TextOutput out) { - if (!BAD_METHOD_NAMES.contains(originalName)) { - return originalName; - } - out.append("@org.jetbrains.jsonProtocol.JsonField(jsonLiteralName=\"").append(originalName).append("\")").newLine(); - return "get" + Character.toUpperCase(originalName.charAt(0)) + originalName.substring(1); - } - - static String capitalizeFirstChar(String s) { - if (!s.isEmpty() && Character.isLowerCase(s.charAt(0))) { - s = Character.toUpperCase(s.charAt(0)) + s.substring(1); - } - return s; - } - - FileUpdater startJavaFile(@NotNull ClassNameScheme nameScheme, Domain domain, String baseName) throws IOException { - return startJavaFile(nameScheme.getPackageNameVirtual(domain.domain()), nameScheme.getShortName(baseName) + ".java"); - } - - public FileUpdater startJavaFile(@NotNull String packageName, @NotNull String filename) { - FileUpdater fileUpdater = fileSet.createFileUpdater(packageName.replace('.', '/') + '/' + filename); - fileUpdater.out.append("// Generated source").newLine().append("package ").append(packageName).semi().newLine().newLine(); - return fileUpdater; - } - - static R switchByType(@NotNull ItemDescriptor typedObject, @NotNull TypeVisitor visitor) { - String refName = typedObject instanceof ItemDescriptor.Referenceable ? ((ItemDescriptor.Referenceable)typedObject).ref() : null; - if (refName != null) { - return visitor.visitRef(refName); - } - String typeName = typedObject.type(); - switch (typeName) { - case BOOLEAN_TYPE: - return visitor.visitBoolean(); - case STRING_TYPE: - if (typedObject.getEnum() != null) { - return visitor.visitEnum(typedObject.getEnum()); - } - return visitor.visitString(); - case INTEGER_TYPE: - case "int": - return visitor.visitInteger(); - case NUMBER_TYPE: - return visitor.visitNumber(); - case ARRAY_TYPE: - return visitor.visitArray(typedObject.items()); - case OBJECT_TYPE: - if (!(typedObject instanceof ItemDescriptor.Type)) { - return visitor.visitObject(null); - } - - List properties = ((ItemDescriptor.Type)typedObject).properties(); - if (properties == null || properties.isEmpty()) { - return visitor.visitMap(); - } - else { - return visitor.visitObject(properties); - } - case ANY_TYPE: - return visitor.visitUnknown(); - case UNKNOWN_TYPE: - return visitor.visitUnknown(); - } - throw new RuntimeException("Unrecognized type " + typeName); - } - - private static void initializeKnownTypes() { - // Code example: - // typeMap.getTypeData("Page", "Cookie").getInput().setJavaTypeName("Object"); - } - - private static final Set BAD_METHOD_NAMES = new HashSet<>(Collections.singletonList("this")); -} \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.kt new file mode 100644 index 000000000000..bac057c6eb2f --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.kt @@ -0,0 +1,288 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.jetbrains.protocolReader + +/** + * Read metamodel and generates set of files with Java classes/interfaces for the protocol. + */ +class Generator [throws(javaClass())] +(outputDir: String, rootPackage: String, requestClassName: String) { + + val jsonProtocolParserClassNames = ArrayList() + val parserRootInterfaceItems = ArrayList() + val typeMap = TypeMap() + + private val fileSet: FileSet + val naming: Naming + + init { + fileSet = FileSet(FileSystems.getDefault().getPath(outputDir)) + naming = Naming(rootPackage, requestClassName) + } + + public class Naming(public val inputPackage: String, public val requestClassName: String) { + public val params: ClassNameScheme + public val additionalParam: ClassNameScheme + public val outputTypedef: ClassNameScheme + + public val commandResult: ClassNameScheme.Input + public val eventData: ClassNameScheme.Input + public val inputValue: ClassNameScheme + public val inputEnum: ClassNameScheme + public val inputTypedef: ClassNameScheme + + public val commonTypedef: ClassNameScheme + + init { + params = ClassNameScheme.Output("", inputPackage) + additionalParam = ClassNameScheme.Output("", inputPackage) + outputTypedef = ClassNameScheme.Output("Typedef", inputPackage) + commonTypedef = ClassNameScheme.Common("Typedef", inputPackage) + commandResult = ClassNameScheme.Input("Result", inputPackage) + eventData = ClassNameScheme.Input("EventData", inputPackage) + inputValue = ClassNameScheme.Input("Value", inputPackage) + inputEnum = ClassNameScheme.Input("", inputPackage) + inputTypedef = ClassNameScheme.Input("Typedef", inputPackage) + } + } + + throws(javaClass()) + fun go(metamodel: Root) { + initializeKnownTypes() + + val domainList = metamodel.domains() + val domainGeneratorMap = HashMap() + for (domain in domainList) { + if (isDomainSkipped(domain)) { + System.out.println("Domain skipped: " + domain.domain()) + continue + } + val domainGenerator = DomainGenerator(this, domain) + domainGeneratorMap.put(domain.domain(), domainGenerator) + domainGenerator.registerTypes() + } + + for (domain in domainList) { + if (!isDomainSkipped(domain)) { + System.out.println("Domain generated: " + domain.domain()) + } + } + + typeMap.setDomainGeneratorMap(domainGeneratorMap) + + for (domainGenerator in domainGeneratorMap.values()) { + domainGenerator.generateCommandsAndEvents() + } + + typeMap.generateRequestedTypes() + generateParserInterfaceList() + generateParserRoot(parserRootInterfaceItems) + fileSet.deleteOtherFiles() + } + + fun resolveType(typedObject: ItemDescriptor, scope: ResolveAndGenerateScope): TypeDescriptor { + val optional = typedObject is ItemDescriptor.Named && (typedObject : ItemDescriptor.Named).optional() + return switchByType(typedObject, object : TypeVisitor { + override fun visitRef(refName: String): TypeDescriptor { + return TypeDescriptor(resolveRefType(scope.getDomainName(), refName, scope.getTypeDirection()), optional) + } + + override fun visitBoolean(): TypeDescriptor { + return TypeDescriptor(BoxableType.BOOLEAN, optional) + } + + override fun visitEnum(enumConstants: List): TypeDescriptor { + assert(scope is MemberScope) + return TypeDescriptor((scope as MemberScope).generateEnum(typedObject.description(), enumConstants), optional) + } + + override fun visitString(): TypeDescriptor { + return TypeDescriptor(BoxableType.STRING, optional) + } + + override fun visitInteger(): TypeDescriptor { + return TypeDescriptor(BoxableType.INT, optional) + } + + override fun visitNumber(): TypeDescriptor { + return TypeDescriptor(BoxableType.NUMBER, optional) + } + + override fun visitMap(): TypeDescriptor { + return TypeDescriptor(BoxableType.MAP, optional) + } + + override fun visitArray(items: ArrayItemType): TypeDescriptor { + val type = scope.resolveType(items).type + return TypeDescriptor(ListType(type), optional, false, type == BoxableType.ANY_STRING) + } + + override fun visitObject(properties: List?): TypeDescriptor { + return TypeDescriptor(scope.generateNestedObject(typedObject.description(), properties!!), optional) + } + + override fun visitUnknown(): TypeDescriptor { + return TypeDescriptor(BoxableType.STRING, optional, false, true) + } + }) + } + + throws(javaClass()) + private fun generateParserInterfaceList() { + val fileUpdater = startJavaFile(naming.inputPackage, PARSER_INTERFACE_LIST_CLASS_NAME + ".java") + // Write classes in stable order. + Collections.sort(jsonProtocolParserClassNames) + + val out = fileUpdater.out + out.append("public class ").append(PARSER_INTERFACE_LIST_CLASS_NAME).openBlock() + out.append("public static final Class[] LIST =").openBlock() + for (name in jsonProtocolParserClassNames) { + out.append(name).append(".class,").newLine() + } + out.closeBlock() + out.semi() + out.closeBlock() + fileUpdater.update() + } + + throws(javaClass()) + private fun generateParserRoot(parserRootInterfaceItems: List) { + val fileUpdater = startJavaFile(naming.inputPackage, READER_INTERFACE_NAME + ".java") + // Write classes in stable order. + Collections.sort(parserRootInterfaceItems) + + val out = fileUpdater.out + out.append("public abstract class ").append(READER_INTERFACE_NAME).space().append("implements org.jetbrains.jsonProtocol.ResponseResultReader").openBlock() + for (item in parserRootInterfaceItems) { + item.writeCode(out) + } + out.newLine().newLine().append("@Override").newLine().append("public Object readResult(String methodName, org.jetbrains.io.JsonReaderEx reader)") + out.openBlock() + + var isNotFirst = false + for (item in parserRootInterfaceItems) { + if (isNotFirst) { + out.append("else ") + } + else { + isNotFirst = true + } + out.append("if (methodName.equals(\"") + if (!item.domain.isEmpty()) { + out.append(item.domain).append('.') + } + out.append(item.name).append('"').append(")) return ") + item.appendReadMethodName(out) + out.append("(reader)").semi().newLine() + } + out.append("else return null").semi() + out.closeBlock() + + out.closeBlock() + fileUpdater.update() + } + + /** + * Resolve absolute (DOMAIN.TYPE) or relative (TYPE) type name + */ + private fun resolveRefType(scopeDomainName: String, refName: String, direction: TypeData.Direction): BoxableType { + val pos = refName.indexOf('.') + val domainName: String + val shortName: String + if (pos == -1) { + domainName = scopeDomainName + shortName = refName + } + else { + domainName = refName.substring(0, pos) + shortName = refName.substring(pos + 1) + } + return typeMap.resolve(domainName, shortName, direction)!! + } + + throws(javaClass()) + fun startJavaFile(nameScheme: ClassNameScheme, domain: Domain, baseName: String): FileUpdater { + return startJavaFile(nameScheme.getPackageNameVirtual(domain.domain()), nameScheme.getShortName(baseName) + ".java") + } + + public fun startJavaFile(packageName: String, filename: String): FileUpdater { + val fileUpdater = fileSet.createFileUpdater(packageName.replace('.', '/') + '/' + filename) + fileUpdater.out.append("// Generated source").newLine().append("package ").append(packageName).semi().newLine().newLine() + return fileUpdater + } + + default object { + private val PARSER_INTERFACE_LIST_CLASS_NAME = "GeneratedReaderInterfaceList" + val READER_INTERFACE_NAME = "ProtocolResponseReader" + + private fun isDomainSkipped(domain: Domain): Boolean { + if (domain.domain() == "CSS" || domain.domain() == "Inspector") { + return false + } + + // todo DOMDebugger + return domain.hidden() || domain.domain() == "DOMDebugger" || domain.domain() == "Timeline" || domain.domain() == "Input" + } + + fun generateMethodNameSubstitute(originalName: String, out: TextOutput): String { + if (!BAD_METHOD_NAMES.contains(originalName)) { + return originalName + } + out.append("@org.jetbrains.jsonProtocol.JsonField(jsonLiteralName=\"").append(originalName).append("\")").newLine() + return "get" + Character.toUpperCase(originalName.charAt(0)) + originalName.substring(1) + } + + fun capitalizeFirstChar(s: String): String { + if (!s.isEmpty() && Character.isLowerCase(s.charAt(0))) { + return Character.toUpperCase(s.charAt(0)) + s.substring(1) + } + return s + } + + fun switchByType(typedObject: ItemDescriptor, visitor: TypeVisitor): R { + val refName = if (typedObject is ItemDescriptor.Referenceable) (typedObject : ItemDescriptor.Referenceable).ref() else null + if (refName != null) { + return visitor.visitRef(refName) + } + val typeName = typedObject.type() + when (typeName) { + ProtocolMetaModel.BOOLEAN_TYPE -> return visitor.visitBoolean() + ProtocolMetaModel.STRING_TYPE -> { + if (typedObject.getEnum() != null) { + return visitor.visitEnum(typedObject.getEnum()!!) + } + return visitor.visitString() + } + ProtocolMetaModel.INTEGER_TYPE, "int" -> return visitor.visitInteger() + ProtocolMetaModel.NUMBER_TYPE -> return visitor.visitNumber() + ProtocolMetaModel.ARRAY_TYPE -> return visitor.visitArray(typedObject.items()) + ProtocolMetaModel.OBJECT_TYPE -> { + if (typedObject !is ItemDescriptor.Type) { + return visitor.visitObject(null) + } + + val properties = (typedObject : ItemDescriptor.Type).properties() + if (properties == null || properties.isEmpty()) { + return visitor.visitMap() + } + else { + return visitor.visitObject(properties) + } + return visitor.visitUnknown() + } + ProtocolMetaModel.ANY_TYPE -> return visitor.visitUnknown() + ProtocolMetaModel.UNKNOWN_TYPE -> return visitor.visitUnknown() + } + throw RuntimeException("Unrecognized type " + typeName) + } + + private fun initializeKnownTypes() { + // Code example: + // typeMap.getTypeData("Page", "Cookie").getInput().setJavaTypeName("Object"); + } + + private val BAD_METHOD_NAMES = HashSet(listOf("this")) + } +} \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/InputClassScope.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/InputClassScope.java deleted file mode 100644 index 99c95d8f5ae3..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/InputClassScope.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.jetbrains.protocolReader; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jsonProtocol.ItemDescriptor.Named; -import org.jetbrains.jsonProtocol.ProtocolMetaModel.ObjectProperty; - -import java.util.List; - -class InputClassScope extends ClassScope { - InputClassScope(DomainGenerator generator, NamePath namePath) { - super(generator, namePath); - } - - void generateDeclarationBody(@NotNull TextOutput out, @NotNull List list) { - for (int i = 0, n = list.size(); i < n; i++) { - Named named = list.get(i); - if (named.description() != null) { - out.doc(named.description()); - } - - String name = getName(named); - String declarationName = Generator.generateMethodNameSubstitute(name, out); - TypeDescriptor typeDescriptor = new InputMemberScope(name).resolveType(named); - typeDescriptor.writeAnnotations(out); - out.append(typeDescriptor.getType().getShortText(getClassContextNamespace())).space().append(declarationName).append("();"); - if (i != (n - 1)) { - out.newLine().newLine(); - } - } - } - - @Override - protected TypeData.Direction getTypeDirection() { - return TypeData.Direction.INPUT; - } - - class InputMemberScope extends MemberScope { - InputMemberScope(String memberName) { - super(InputClassScope.this, memberName); - } - - @Override - public BoxableType generateEnum(final String description, final List enumConstants) { - final String enumName = Generator.capitalizeFirstChar(getMemberName()); - addMember(new TextOutConsumer() { - @Override - public void append(TextOutput out) { - out.newLine().doc(description); - Enums.appendEnums(enumConstants, enumName, true, out); - } - }); - return new StandaloneType(new NamePath(enumName, getClassContextNamespace()), "writeEnum"); - } - - @Override - public BoxableType generateNestedObject(final String description, final List propertyList) { - final String objectName = Generator.capitalizeFirstChar(getMemberName()); - addMember(new TextOutConsumer() { - @Override - public void append(TextOutput out) { - out.newLine().doc(description); - if (propertyList == null) { - out.append("@org.jetbrains.jsonProtocol.JsonType(allowsOtherProperties=true)").newLine(); - out.append("public interface ").append(objectName).append(" extends org.jetbrains.jsonProtocol.JsonObjectBased").openBlock(); - } - else { - out.append("@org.jetbrains.jsonProtocol.JsonType").newLine(); - out.append("public interface ").append(objectName).openBlock(); - for (ObjectProperty property : propertyList) { - out.doc(property.description()); - - String methodName = Generator.generateMethodNameSubstitute(getName(property), out); - MemberScope memberScope = new InputMemberScope(getName(property)); - TypeDescriptor propertyTypeData = memberScope.resolveType(property); - propertyTypeData.writeAnnotations(out); - - out.append(propertyTypeData.getType().getShortText(getClassContextNamespace()) + ' ' + methodName + "();").newLine(); - } - } - out.closeBlock(); - } - }); - return new StandaloneType(new NamePath(objectName, getClassContextNamespace()), "writeMessage"); - } - } -} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/InputClassScope.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/InputClassScope.kt new file mode 100644 index 000000000000..bbbce17f5b1a --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/InputClassScope.kt @@ -0,0 +1,73 @@ +package org.jetbrains.protocolReader + +class InputClassScope(generator: DomainGenerator, namePath: NamePath) : ClassScope(generator, namePath) { + + fun generateDeclarationBody(out: TextOutput, list: List) { + run { + var i = 0 + val n = list.size() + while (i < n) { + val named = list.get(i) + if (named.description() != null) { + out.doc(named.description()) + } + + val name = ClassScope.getName(named) + val declarationName = Generator.generateMethodNameSubstitute(name, out) + val typeDescriptor = InputMemberScope(name).resolveType(named) + typeDescriptor.writeAnnotations(out) + out.append(typeDescriptor.type.getShortText(classContextNamespace)).space().append(declarationName).append("();") + if (i != (n - 1)) { + out.newLine().newLine() + } + i++ + } + } + } + + override fun getTypeDirection(): TypeData.Direction { + return TypeData.Direction.INPUT + } + + inner class InputMemberScope(memberName: String) : MemberScope(this@InputClassScope, memberName) { + override fun generateEnum(description: String?, enumConstants: List): BoxableType { + val enumName = Generator.capitalizeFirstChar(memberName) + addMember(object : TextOutConsumer { + override fun append(out: TextOutput) { + out.newLine().doc(description) + Enums.appendEnums(enumConstants, enumName, true, out) + } + }) + return StandaloneType(NamePath(enumName, classContextNamespace), "writeEnum") + } + + override fun generateNestedObject(description: String?, properties: List?): BoxableType { + val objectName = Generator.capitalizeFirstChar(memberName) + addMember(object : TextOutConsumer { + override fun append(out: TextOutput) { + out.newLine().doc(description) + if (properties == null) { + out.append("@org.jetbrains.jsonProtocol.JsonType(allowsOtherProperties=true)").newLine() + out.append("public interface ").append(objectName).append(" extends org.jetbrains.jsonProtocol.JsonObjectBased").openBlock() + } + else { + out.append("@org.jetbrains.jsonProtocol.JsonType").newLine() + out.append("public interface ").append(objectName).openBlock() + for (property in properties) { + out.doc(property.description()) + + val methodName = Generator.generateMethodNameSubstitute(ClassScope.getName(property), out) + val memberScope = InputMemberScope(ClassScope.getName(property)) + val propertyTypeData = memberScope.resolveType(property) + propertyTypeData.writeAnnotations(out) + + out.append(propertyTypeData.type.getShortText(classContextNamespace) + ' ' + methodName + "();").newLine() + } + } + out.closeBlock() + } + }) + return StandaloneType(NamePath(objectName, classContextNamespace), "writeMessage") + } + } +} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ListType.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ListType.java deleted file mode 100644 index f41769ad77c5..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ListType.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.jetbrains.protocolReader; - -import org.jetbrains.annotations.NotNull; - -class ListType extends BoxableType { - private final BoxableType itemType; - - public ListType(@NotNull BoxableType itemType) { - this.itemType = itemType; - } - - @Override - String getWriteMethodName() { - if (itemType == STRING) { - return "writeStringList"; - } - else if (itemType == LONG) { - return "writeLongArray"; - } - else if (itemType == INT) { - return "writeIntArray"; - } - else if (itemType == NUMBER) { - return "writeDoubleArray"; - } - return "writeList"; - } - - @Override - String getFullText() { - if (itemType == LONG || itemType == INT || itemType == NUMBER) { - return itemType.getFullText() + "[]"; - } - return "java.util.List<" + itemType.getFullText() + '>'; - } - - @Override - String getShortText(NamePath contextNamespace) { - if (itemType == LONG || itemType == INT || itemType == NUMBER) { - return itemType.getFullText() + "[]"; - } - return "java.util.List<" + itemType.getShortText(contextNamespace) + '>'; - } -} \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ListType.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ListType.kt new file mode 100644 index 000000000000..737fc1d8feeb --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ListType.kt @@ -0,0 +1,34 @@ +package org.jetbrains.protocolReader + +open class ListType(private val itemType: BoxableType) : BoxableType() { + + override fun getWriteMethodName(): String { + if (itemType == BoxableType.STRING) { + return "writeStringList" + } + else if (itemType == BoxableType.LONG) { + return "writeLongArray" + } + else if (itemType == BoxableType.INT) { + return "writeIntArray" + } + else if (itemType == BoxableType.NUMBER) { + return "writeDoubleArray" + } + return "writeList" + } + + override fun getFullText(): String { + if (itemType == BoxableType.LONG || itemType == BoxableType.INT || itemType == BoxableType.NUMBER) { + return "${itemType.getFullText()}[]" + } + return "java.util.List<" + itemType.getFullText() + '>' + } + + override fun getShortText(contextNamespace: NamePath): String { + if (itemType == BoxableType.LONG || itemType == BoxableType.INT || itemType == BoxableType.NUMBER) { + return "${itemType.getFullText()}[]" + } + return "java.util.List<" + itemType.getShortText(contextNamespace) + '>' + } +} \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MemberScope.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MemberScope.java deleted file mode 100644 index 78a83a9127ca..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MemberScope.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.jetbrains.protocolReader; - -import org.jetbrains.jsonProtocol.ItemDescriptor; -import org.jetbrains.jsonProtocol.ProtocolMetaModel; - -import java.util.List; - -/** - * Member scope is used to generate additional types that are used only from method. - * These types will be named after this method. - */ -abstract class MemberScope implements ResolveAndGenerateScope { - private final String memberName; - private final ClassScope classScope; - - MemberScope(ClassScope classScope, String memberName) { - this.classScope = classScope; - this.memberName = memberName; - } - - @Override - public TypeDescriptor resolveType(T typedObject) { - return classScope.generator.generator.resolveType(typedObject, this); - } - - protected String getMemberName() { - return memberName; - } - - public abstract BoxableType generateEnum(String description, List enumConstants); - public abstract BoxableType generateNestedObject(String description, List propertyList); - - @Override - public String getDomainName() { - return classScope.generator.domain.domain(); - } - - @Override - public TypeData.Direction getTypeDirection() { - return classScope.getTypeDirection(); - } -} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MemberScope.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MemberScope.kt new file mode 100644 index 000000000000..65442ed6c94e --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MemberScope.kt @@ -0,0 +1,17 @@ +package org.jetbrains.protocolReader + +/** + * Member scope is used to generate additional types that are used only from method. + * These types will be named after this method. + */ +abstract class MemberScope(private val classScope: ClassScope, protected val memberName: String) : ResolveAndGenerateScope { + override fun resolveType(typedObject: T): TypeDescriptor { + return classScope.generator.generator.resolveType(typedObject, this) + } + + public abstract fun generateEnum(description: String?, enumConstants: List): BoxableType + + override fun getDomainName() = classScope.generator.domain.domain() + + override fun getTypeDirection() = classScope.getTypeDirection() +} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MyCreateStandaloneTypeBindingVisitorBase.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MyCreateStandaloneTypeBindingVisitorBase.java deleted file mode 100644 index 180a8fc28adb..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MyCreateStandaloneTypeBindingVisitorBase.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.jetbrains.protocolReader; - -import org.jetbrains.jsonProtocol.ItemDescriptor; -import org.jetbrains.jsonProtocol.ProtocolMetaModel; - -import java.io.IOException; -import java.util.List; - -class MyCreateStandaloneTypeBindingVisitorBase extends CreateStandaloneTypeBindingVisitorBase { - private final String name; - private final DomainGenerator generator; - - public MyCreateStandaloneTypeBindingVisitorBase(DomainGenerator generator, ProtocolMetaModel.StandaloneType type, String name) { - super(generator, type); - this.generator = generator; - this.name = name; - } - - @Override - public StandaloneTypeBinding visitObject(List properties) { - return new StandaloneTypeBinding() { - @Override - public BoxableType getJavaType() { - return new StandaloneType(generator.generator.naming.additionalParam.getFullName(generator.domain.domain(), name), "writeMessage"); - } - - @Override - public void generate() throws IOException { - generator.generateCommandAdditionalParam(getType()); - } - - @Override - public TypeData.Direction getDirection() { - return TypeData.Direction.OUTPUT; - } - }; - } - - @Override - public StandaloneTypeBinding visitEnum(List enumConstants) { - throw new RuntimeException(); - } - - @Override - public StandaloneTypeBinding visitArray(final ProtocolMetaModel.ArrayItemType items) { - return generator.createTypedefTypeBinding(getType(), new StandaloneTypeBinding.Target() { - @Override - public BoxableType resolve(final ResolveContext context) { - return new ListType(generator.generator.resolveType(items, new ResolveAndGenerateScope() { - // This class is responsible for generating ad hoc type. - // If we ever are to do it, we should generate into string buffer and put strings inside TypeDef class - @Override - public String getDomainName() { - return generator.domain.domain(); - } - - @Override - public TypeData.Direction getTypeDirection() { - return TypeData.Direction.OUTPUT; - } - - @Override - public TypeDescriptor resolveType(T typedObject) { - throw new UnsupportedOperationException(); - } - - @Override - public BoxableType generateNestedObject(String description, List properties) { - return context.generateNestedObject("Item", description, properties); - } - }).getType()); - } - }, generator.generator.naming.outputTypedef, TypeData.Direction.OUTPUT); - } -} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MyCreateStandaloneTypeBindingVisitorBase.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MyCreateStandaloneTypeBindingVisitorBase.kt new file mode 100644 index 000000000000..560c41279bc4 --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MyCreateStandaloneTypeBindingVisitorBase.kt @@ -0,0 +1,44 @@ +package org.jetbrains.protocolReader + +class MyCreateStandaloneTypeBindingVisitorBase(private val generator: DomainGenerator, type: ProtocolMetaModel.StandaloneType, private val name: String) : CreateStandaloneTypeBindingVisitorBase(generator, type) { + + override fun visitObject(properties: List?): StandaloneTypeBinding { + return object : StandaloneTypeBinding { + override fun getJavaType(): BoxableType { + return StandaloneType(generator.generator.naming.additionalParam.getFullName(generator.domain.domain(), name), "writeMessage") + } + + override fun generate() { + generator.generateCommandAdditionalParam(type) + } + + override fun getDirection(): TypeData.Direction? { + return TypeData.Direction.OUTPUT + } + } + } + + override fun visitEnum(enumConstants: List): StandaloneTypeBinding { + throw RuntimeException() + } + + override fun visitArray(items: ProtocolMetaModel.ArrayItemType): StandaloneTypeBinding { + return generator.createTypedefTypeBinding(type, object : StandaloneTypeBinding.Target { + override fun resolve(context: StandaloneTypeBinding.Target.ResolveContext): BoxableType { + return ListType(generator.generator.resolveType(items, object : ResolveAndGenerateScope { + // This class is responsible for generating ad hoc type. + // If we ever are to do it, we should generate into string buffer and put strings inside TypeDef class + override fun getDomainName() = generator.domain.domain() + + override fun getTypeDirection() = TypeData.Direction.OUTPUT + + override fun resolveType(typedObject: T) = throw UnsupportedOperationException() + + override fun generateNestedObject(description: String?, properties: List?): BoxableType { + return context.generateNestedObject("Item", description, properties) + } + }).type) + } + }, generator.generator.naming.outputTypedef, TypeData.Direction.OUTPUT) + } +} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/NamePath.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/NamePath.java deleted file mode 100644 index b516d7734e02..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/NamePath.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.jetbrains.protocolReader; - -class NamePath { - private final String lastComponent; - private final NamePath parent; - - NamePath(String component) { - this(component, null); - } - - NamePath(String component, NamePath parent) { - lastComponent = component; - this.parent = parent; - } - - NamePath getParent() { - return parent; - } - - String getLastComponent() { - return lastComponent; - } - - int getLength() { - int res = 1; - for (NamePath current = this; current != null; current = current.getParent()) { - res++; - } - return res; - } - - String getFullText() { - StringBuilder result = new StringBuilder(); - fillFullPath(result); - return result.toString(); - } - - private void fillFullPath(StringBuilder result) { - if (parent != null) { - parent.fillFullPath(result); - result.append('.'); - } - result.append(lastComponent); - } -} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/NamePath.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/NamePath.kt new file mode 100644 index 000000000000..2f1ded3bd443 --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/NamePath.kt @@ -0,0 +1,30 @@ +package org.jetbrains.protocolReader + +class NamePath(val lastComponent: String, val parent: NamePath? = null) { + + fun getLength(): Int { + var res = 1 + run { + var current: NamePath? = this + while (current != null) { + res++ + current = current!!.parent + } + } + return res + } + + fun getFullText(): String { + val result = StringBuilder() + fillFullPath(result) + return result.toString() + } + + private fun fillFullPath(result: StringBuilder) { + if (parent != null) { + parent.fillFullPath(result) + result.append('.') + } + result.append(lastComponent) + } +} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/OutputClassScope.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/OutputClassScope.java deleted file mode 100644 index 76a309368f32..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/OutputClassScope.java +++ /dev/null @@ -1,245 +0,0 @@ -package org.jetbrains.protocolReader; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.io.JsonReaderEx; -import org.jetbrains.jsonProtocol.ItemDescriptor; -import org.jetbrains.jsonProtocol.ProtocolMetaModel; - -import java.util.ArrayList; -import java.util.List; - -class OutputClassScope extends ClassScope { - OutputClassScope(@NotNull DomainGenerator generator, @NotNull NamePath classNamePath) { - super(generator, classNamePath); - } - -

void generate(@NotNull TextOutput out, @Nullable List

parameters) { - if (parameters == null) { - return; - } - - List

mandatoryParameters = new ArrayList<>(); - List

optionalParameters = new ArrayList<>(); - for (P parameter : parameters) { - if (parameter.optional()) { - optionalParameters.add(parameter); - } - else { - mandatoryParameters.add(parameter); - } - } - - if (!mandatoryParameters.isEmpty()) { - generateConstructor(out, mandatoryParameters, null); - if (mandatoryParameters.size() == 1) { - P parameter = mandatoryParameters.get(0); - TypeDescriptor typeData = new OutputMemberScope(getName(parameter)).resolveType(parameter); - if (typeData.getType().getFullText().equals("int[]")) { - BoxableType[] types = new BoxableType[mandatoryParameters.size()]; - types[0] = new ListType(BoxableType.INT) { - @Override - String getShortText(NamePath contextNamespace) { - return getFullText(); - } - - @Override - String getFullText() { - return "gnu.trove.TIntArrayList"; - } - - @Override - String getWriteMethodName() { - return "writeIntList"; - } - }; - - out.newLine().newLine(); - generateConstructor(out, mandatoryParameters, types); - - types[0] = new ListType(BoxableType.INT) { - @Override - String getShortText(NamePath contextNamespace) { - return getFullText(); - } - - @Override - String getFullText() { - return "int"; - } - - @Override - String getWriteMethodName() { - return "writeSingletonIntArray"; - } - }; - - out.newLine().newLine(); - generateConstructor(out, mandatoryParameters, types); - } - } - } - - // generate enum classes after constructor - for (P parameter : parameters) { - if (parameter.getEnum() != null) { - out.newLine().newLine(); - appendEnumClass(out, parameter.description(), parameter.getEnum(), Generator.capitalizeFirstChar((parameter.name()))); - } - } - - for (P parameter : optionalParameters) { - out.newLine().newLine(); - if (parameter.description() != null) { - out.append("/**").newLine().append(" * @param v ").append(parameter.description()).newLine().append(" */").newLine(); - } - - CharSequence type = new OutputMemberScope(parameter.name()).resolveType(parameter).getType().getShortText(getClassContextNamespace()); - if (type.equals(JsonReaderEx.class.getCanonicalName())) { - type = "String"; - } - - out.append("public ").append(getShortClassName()); - out.space().append(parameter.name()).append("(").append(type); - out.space().append("v").append(")").openBlock(); - appendWriteValueInvocation(out, parameter, "v", null); - out.newLine().append("return this;"); - out.closeBlock(); - } - } - - private

void generateConstructor(@NotNull TextOutput out, @NotNull List

parameters, @Nullable BoxableType[] parameterTypes) { - boolean hasDoc = false; - for (P parameter : parameters) { - if (parameter.description() != null) { - hasDoc = true; - break; - } - } - if (hasDoc) { - out.append("/**").newLine(); - for (P parameter : parameters) { - if (parameter.description() != null) { - out.append(" * @param " + parameter.name() + ' ' + parameter.description()).newLine(); - } - } - out.append(" */").newLine(); - } - out.append("public " + getShortClassName() + '('); - - if (parameterTypes == null) { - parameterTypes = new BoxableType[parameters.size()]; - } - writeMethodParameters(out, parameters, parameterTypes); - out.append(')'); - - out.openBlock(false); - writeWriteCalls(out, parameters, parameterTypes, null); - out.closeBlock(); - } - -

void writeWriteCalls(@NotNull TextOutput out, @NotNull List

parameters, @NotNull BoxableType[] parameterTypes, @Nullable String qualifier) { - for (int i = 0, size = parameters.size(); i < size; i++) { - out.newLine(); - - if (qualifier != null) { - out.append(qualifier).append('.'); - } - - P parameter = parameters.get(i); - appendWriteValueInvocation(out, parameter, parameter.name(), parameterTypes[i]); - } - } - -

void writeMethodParameters(@NotNull TextOutput out, @NotNull List

parameters, @NotNull BoxableType[] parameterTypes) { - for (int i = 0, length = parameterTypes.length; i < length; i++) { - if (parameterTypes[i] == null) { - P parameter = parameters.get(i); - parameterTypes[i] = new OutputMemberScope(parameter.name()).resolveType(parameter).getType(); - } - } - - boolean needComa = false; - for (int i = 0, size = parameters.size(); i < size; i++) { - if (needComa) { - out.comma(); - } - else { - needComa = true; - } - - out.append(parameterTypes[i].getShortText(getClassContextNamespace())); - out.space().append(parameters.get(i).name()); - } - } - - private void appendWriteValueInvocation(TextOutput out, ItemDescriptor.Named parameter, String valueRefName, @Nullable BoxableType type) { - if (type == null) { - type = new OutputMemberScope(parameter.name()).resolveType(parameter).getType(); - } - - boolean blockOpened = false; - if (parameter.optional()) { - String nullValue; - if (parameter.name().equals("columnNumber") || parameter.name().equals("column")) { - // todo generic solution - nullValue = "-1"; - } - else { - nullValue = null; - } - - if (nullValue != null) { - blockOpened = true; - out.append("if (v != ").append(nullValue).append(")").openBlock(); - } - else if (parameter.name().equals("enabled")) { - blockOpened = true; - out.append("if (!v)").openBlock(); - } - else if (parameter.name().equals("ignoreCount")) { - blockOpened = true; - out.append("if (v > 0)").openBlock(); - } - } - // todo CallArgument (we should allow write null as value) - out.append(parameter.name().equals("value") && type.getWriteMethodName().equals("writeString") ? "writeNullableString" : type.getWriteMethodName()).append("("); - out.quote(parameter.name()).comma().append(valueRefName).append(");"); - if (blockOpened) { - out.closeBlock(); - } - } - - @Override - protected TypeData.Direction getTypeDirection() { - return TypeData.Direction.OUTPUT; - } - - class OutputMemberScope extends MemberScope { - protected OutputMemberScope(String memberName) { - super(OutputClassScope.this, memberName); - } - - @Override - public BoxableType generateEnum(final String description, final List enumConstants) { - return new StandaloneType(new NamePath(Generator.capitalizeFirstChar(getMemberName()), getClassContextNamespace()), "writeEnum"); - } - - @Override - public BoxableType generateNestedObject(String description, List propertyList) { - throw new UnsupportedOperationException(); - } - } - - private static void appendEnumClass(TextOutput out, String description, List enumConstants, String enumName) { - out.doc(description); - Enums.appendEnums(enumConstants, enumName, false, out); - out.newLine().append("private final String protocolValue;").newLine(); - out.newLine().append(enumName).append("(String protocolValue)").openBlock(); - out.append("this.protocolValue = protocolValue;").closeBlock(); - - out.newLine().newLine().append("public String toString()").openBlock(); - out.append("return protocolValue;").closeBlock(); - out.closeBlock(); - } -} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/OutputClassScope.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/OutputClassScope.kt new file mode 100644 index 000000000000..b0e93d5963b1 --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/OutputClassScope.kt @@ -0,0 +1,225 @@ +package org.jetbrains.protocolReader + +class OutputClassScope(generator: DomainGenerator, classNamePath: NamePath) : ClassScope(generator, classNamePath) { + fun

generate(out: TextOutput, parameters: List

?) { + if (parameters == null) { + return + } + + val mandatoryParameters = ArrayList

() + val optionalParameters = ArrayList

() + for (parameter in parameters) { + if (parameter.optional()) { + optionalParameters.add(parameter) + } + else { + mandatoryParameters.add(parameter) + } + } + + if (!mandatoryParameters.isEmpty()) { + generateConstructor(out, mandatoryParameters) + if (mandatoryParameters.size() == 1) { + val parameter = mandatoryParameters.get(0) + val typeData = OutputMemberScope(ClassScope.getName(parameter)).resolveType

(parameter) + if (typeData.type.getFullText() == "int[]") { + val types = arrayOfNulls(mandatoryParameters.size()) + types[0] = object : ListType(BoxableType.INT) { + override fun getShortText(contextNamespace: NamePath): String { + return getFullText() + } + + override fun getFullText(): String { + return "gnu.trove.TIntArrayList" + } + + override fun getWriteMethodName(): String { + return "writeIntList" + } + } + + out.newLine().newLine() + generateConstructor(out, mandatoryParameters, types) + + types[0] = object : ListType(BoxableType.INT) { + override fun getShortText(contextNamespace: NamePath): String { + return getFullText() + } + + override fun getFullText(): String { + return "int" + } + + override fun getWriteMethodName(): String { + return "writeSingletonIntArray" + } + } + + out.newLine().newLine() + generateConstructor(out, mandatoryParameters, types) + } + } + } + + // generate enum classes after constructor + for (parameter in parameters) { + if (parameter.getEnum() != null) { + out.newLine().newLine() + appendEnumClass(out, parameter.description(), parameter.getEnum()!!, Generator.capitalizeFirstChar((parameter.name()))) + } + } + + for (parameter in optionalParameters) { + out.newLine().newLine() + if (parameter.description() != null) { + out.append("/**").newLine().append(" * @param v ").append(parameter.description()!!).newLine().append(" */").newLine() + } + + var type: CharSequence = OutputMemberScope(parameter.name()).resolveType

(parameter).type.getShortText(classContextNamespace) + if (type == javaClass().getCanonicalName()) { + type = "String" + } + + out.append("public ").append(getShortClassName()) + out.space().append(parameter.name()).append("(").append(type) + out.space().append("v").append(")").openBlock() + appendWriteValueInvocation(out, parameter, "v") + out.newLine().append("return this;") + out.closeBlock() + } + } + + private fun

generateConstructor(out: TextOutput, parameters: List

, parameterTypes: Array = arrayOfNulls(parameters.size())) { + var hasDoc = false + for (parameter in parameters) { + if (parameter.description() != null) { + hasDoc = true + break + } + } + if (hasDoc) { + out.append("/**").newLine() + for (parameter in parameters) { + if (parameter.description() != null) { + out.append(" * @param " + parameter.name() + ' ' + parameter.description()).newLine() + } + } + out.append(" */").newLine() + } + out.append("public " + getShortClassName() + '(') + + writeMethodParameters(out, parameters, parameterTypes) + out.append(')') + + out.openBlock(false) + writeWriteCalls(out, parameters, parameterTypes, null) + out.closeBlock() + } + + fun

writeWriteCalls(out: TextOutput, parameters: List

, parameterTypes: Array, qualifier: String?) { + run { + var i = 0 + val size = parameters.size() + while (i < size) { + out.newLine() + + if (qualifier != null) { + out.append(qualifier).append('.') + } + + val parameter = parameters.get(i) + appendWriteValueInvocation(out, parameter, parameter.name(), parameterTypes[i]!!) + i++ + } + } + } + + fun

writeMethodParameters(out: TextOutput, parameters: List

, parameterTypes: Array) { + run { + var i = 0 + val length = parameterTypes.size() + while (i < length) { + if (parameterTypes[i] == null) { + val parameter = parameters.get(i) + parameterTypes[i] = OutputMemberScope(parameter.name()).resolveType

(parameter).type + } + i++ + } + } + + var needComa = false + run { + var i = 0 + val size = parameters.size() + while (i < size) { + if (needComa) { + out.comma() + } + else { + needComa = true + } + + out.append(parameterTypes[i]!!.getShortText(classContextNamespace)) + out.space().append(parameters.get(i).name()) + i++ + } + } + } + + private fun appendWriteValueInvocation(out: TextOutput, parameter: ItemDescriptor.Named, valueRefName: String, type: BoxableType = OutputMemberScope(parameter.name()).resolveType(parameter).type) { + var blockOpened = false + if (parameter.optional()) { + val nullValue: String? + if (parameter.name() == "columnNumber" || parameter.name() == "column") { + // todo generic solution + nullValue = "-1" + } + else { + nullValue = null + } + + if (nullValue != null) { + blockOpened = true + out.append("if (v != ").append(nullValue).append(")").openBlock() + } + else if (parameter.name() == "enabled") { + blockOpened = true + out.append("if (!v)").openBlock() + } + else if (parameter.name() == "ignoreCount") { + blockOpened = true + out.append("if (v > 0)").openBlock() + } + } + // todo CallArgument (we should allow write null as value) + out.append(if (parameter.name() == "value" && type.getWriteMethodName() == "writeString") "writeNullableString" else type.getWriteMethodName()).append("(") + out.quote(parameter.name()).comma().append(valueRefName).append(");") + if (blockOpened) { + out.closeBlock() + } + } + + override fun getTypeDirection(): TypeData.Direction { + return TypeData.Direction.OUTPUT + } + + inner class OutputMemberScope(memberName: String) : MemberScope(this@OutputClassScope, memberName) { + override fun generateEnum(description: String?, enumConstants: List): BoxableType { + return StandaloneType(NamePath(Generator.capitalizeFirstChar(memberName), classContextNamespace), "writeEnum") + } + + override fun generateNestedObject(description: String?, properties: List?) = throw UnsupportedOperationException() + } + + private fun appendEnumClass(out: TextOutput, description: String?, enumConstants: List, enumName: String) { + out.doc(description) + Enums.appendEnums(enumConstants, enumName, false, out) + out.newLine().append("private final String protocolValue;").newLine() + out.newLine().append(enumName).append("(String protocolValue)").openBlock() + out.append("this.protocolValue = protocolValue;").closeBlock() + + out.newLine().newLine().append("public String toString()").openBlock() + out.append("return protocolValue;").closeBlock() + out.closeBlock() + } +} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ParserRootInterfaceItem.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ParserRootInterfaceItem.java deleted file mode 100644 index e84c641ff9c3..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ParserRootInterfaceItem.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.jetbrains.protocolReader; - -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; - -class ParserRootInterfaceItem implements Comparable { - final String domain; - final String name; - private final ClassNameScheme.Input nameScheme; - final String fullName; - - public ParserRootInterfaceItem(String domain, String name, ClassNameScheme.Input nameScheme) { - this.domain = domain; - this.name = name; - this.nameScheme = nameScheme; - fullName = nameScheme.getFullName(domain, name).getFullText(); - } - - void writeCode(TextOutput out) throws IOException { - out.append("@org.jetbrains.jsonProtocol.JsonParseMethod").newLine(); - out.append("public abstract ").append(fullName).space(); - appendReadMethodName(out); - out.append("(").append(Util.JSON_READER_PARAMETER_DEF).append(")").semi().newLine(); - } - - void appendReadMethodName(TextOutput out) { - out.append(nameScheme.getParseMethodName(domain, name)); - } - - @Override - public int compareTo(@NotNull ParserRootInterfaceItem o) { - return fullName.compareTo(o.fullName); - } -} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ParserRootInterfaceItem.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ParserRootInterfaceItem.kt new file mode 100644 index 000000000000..eb0cc1ee1b4e --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ParserRootInterfaceItem.kt @@ -0,0 +1,26 @@ +package org.jetbrains.protocolReader + +import org.jetbrains.protocolReader.ParserRootInterfaceItem + +class ParserRootInterfaceItem(val domain: String, val name: String, private val nameScheme: ClassNameScheme.Input) : Comparable { + val fullName: String + + init { + fullName = nameScheme.getFullName(domain, name).getFullText() + } + + fun writeCode(out: TextOutput) { + out.append("@org.jetbrains.jsonProtocol.JsonParseMethod").newLine() + out.append("public abstract ").append(fullName).space() + appendReadMethodName(out) + out.append("(").append(JSON_READER_PARAMETER_DEF).append(")").semi().newLine() + } + + fun appendReadMethodName(out: TextOutput) { + out.append(nameScheme.getParseMethodName(domain, name)) + } + + override fun compareTo(other: ParserRootInterfaceItem): Int { + return fullName.compareTo(other.fullName) + } +} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ProtocolModelGenerator.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ProtocolModelGenerator.java deleted file mode 100644 index 7866e74a7f48..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ProtocolModelGenerator.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.jetbrains.protocolReader; - -import org.jetbrains.io.JsonReaderEx; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jsonProtocol.ProtocolSchemaReaderImpl; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.nio.file.FileSystems; -import java.nio.file.Files; - -public class ProtocolModelGenerator { - public static void main(String[] args) throws IOException { - String outputDir = args[0]; - String schemaUrl = args[1]; - byte[] bytes; - if (schemaUrl.startsWith("http")) { - bytes = loadBytes(new URL(schemaUrl).openStream()); - } - else { - bytes = Files.readAllBytes(FileSystems.getDefault().getPath(schemaUrl)); - } - JsonReaderEx reader = new JsonReaderEx(new String(bytes, StandardCharsets.UTF_8)); - reader.setLenient(true); - new Generator(outputDir, args[2], args[3]).go(new ProtocolSchemaReaderImpl().parseRoot(reader)); - } - - @NotNull - public static byte[] loadBytes(@NotNull InputStream stream) throws IOException { - ByteArrayOutputStream buffer = new ByteArrayOutputStream(Math.max(stream.available(), 16 * 1024)); - byte[] bytes = new byte[1024 * 20]; - while (true) { - int n = stream.read(bytes, 0, bytes.length); - if (n <= 0) { - break; - } - buffer.write(bytes, 0, n); - } - buffer.close(); - return buffer.toByteArray(); - } -} \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ProtocolModelGenerator.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ProtocolModelGenerator.kt new file mode 100644 index 000000000000..9ebbe79afa25 --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ProtocolModelGenerator.kt @@ -0,0 +1,40 @@ +package org.jetbrains.protocolReader + +import org.jetbrains.protocolReader.ProtocolModelGenerator + +public class ProtocolModelGenerator { + default object { + throws(javaClass()) + public fun main(args: Array) { + val outputDir = args[0] + val schemaUrl = args[1] + val bytes: ByteArray + if (schemaUrl.startsWith("http")) { + bytes = loadBytes(URL(schemaUrl).openStream()) + } + else { + bytes = Files.readAllBytes(FileSystems.getDefault().getPath(schemaUrl)) + } + val reader = JsonReaderEx(String(bytes, StandardCharsets.UTF_8)) + reader.setLenient(true) + Generator(outputDir, args[2], args[3]).go(ProtocolSchemaReaderImpl().parseRoot(reader)) + } + + throws(javaClass()) + public fun loadBytes(stream: InputStream): ByteArray { + val buffer = ByteArrayOutputStream(Math.max(stream.available(), 16 * 1024)) + val bytes = ByteArray(1024 * 20) + while (true) { + val n = stream.read(bytes, 0, bytes.size()) + if (n <= 0) { + break + } + buffer.write(bytes, 0, n) + } + buffer.close() + return buffer.toByteArray() + } + } +} + +fun main(args: Array) = ProtocolModelGenerator.main(args) \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ResolveAndGenerateScope.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ResolveAndGenerateScope.java deleted file mode 100644 index c43c9ff7deff..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ResolveAndGenerateScope.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.jetbrains.protocolReader; - -import org.jetbrains.jsonProtocol.ItemDescriptor; -import org.jetbrains.jsonProtocol.ProtocolMetaModel; - -import java.util.List; - -interface ResolveAndGenerateScope { - String getDomainName(); - TypeData.Direction getTypeDirection(); - - TypeDescriptor resolveType(T typedObject); - - BoxableType generateNestedObject(String description, - List properties); -} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ResolveAndGenerateScope.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ResolveAndGenerateScope.kt new file mode 100644 index 000000000000..28dea57a46d6 --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ResolveAndGenerateScope.kt @@ -0,0 +1,10 @@ +package org.jetbrains.protocolReader + +trait ResolveAndGenerateScope { + public fun getDomainName(): String + public fun getTypeDirection(): TypeData.Direction + + public fun resolveType(typedObject: T): TypeDescriptor + + public fun generateNestedObject(description: String?, properties: List?): BoxableType +} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/StandaloneType.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/StandaloneType.java deleted file mode 100644 index 540b2052c408..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/StandaloneType.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.jetbrains.protocolReader; - -class StandaloneType extends BoxableType { - private final NamePath namePath; - private final String writeMethodName; - - StandaloneType(NamePath namePath, String writeMethodName) { - this.namePath = namePath; - this.writeMethodName = writeMethodName; - } - - @Override - String getWriteMethodName() { - return writeMethodName; - } - - @Override - CharSequence getFullText() { - return namePath.getFullText(); - } - - @Override - String getShortText(NamePath contextNamespace) { - int nameLength = namePath.getLength(); - int contextLength = contextNamespace.getLength(); - if (nameLength > contextLength) { - StringBuilder builder = subtractContextRecursively(namePath, nameLength - contextLength, contextNamespace); - if (builder != null) { - return builder.toString(); - } - } - return namePath.getFullText(); - } - - private static StringBuilder subtractContextRecursively(NamePath namePos, int count, NamePath prefix) { - if (count > 1) { - StringBuilder result = subtractContextRecursively(namePos.getParent(), count - 1, prefix); - if (result == null) { - return null; - } - result.append('.'); - result.append(namePos.getLastComponent()); - return result; - } - else { - String nameComponent = namePos.getLastComponent(); - namePos = namePos.getParent(); - do { - if (!namePos.getLastComponent().equals(prefix.getLastComponent())) { - return null; - } - namePos = namePos.getParent(); - prefix = prefix.getParent(); - } - while (namePos != null); - - StringBuilder result = new StringBuilder(); - result.append(nameComponent); - return result; - } - } -} \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/StandaloneType.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/StandaloneType.kt new file mode 100644 index 000000000000..e93b18b5005b --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/StandaloneType.kt @@ -0,0 +1,53 @@ +package org.jetbrains.protocolReader + +class StandaloneType(private val namePath: NamePath, private val writeMethodName: String) : BoxableType() { + override fun getWriteMethodName(): String { + return writeMethodName + } + + override fun getFullText(): CharSequence { + return namePath.getFullText() + } + + override fun getShortText(contextNamespace: NamePath): String { + val nameLength = namePath.getLength() + val contextLength = contextNamespace.getLength() + if (nameLength > contextLength) { + val builder = subtractContextRecursively(namePath, nameLength - contextLength, contextNamespace) + if (builder != null) { + return builder.toString() + } + } + return namePath.getFullText() + } + + private fun subtractContextRecursively(namePos: NamePath?, count: Int, prefix: NamePath): StringBuilder? { + var namePos = namePos + var prefix = prefix + if (count > 1) { + val result = subtractContextRecursively(namePos!!.parent, count - 1, prefix) + if (result == null) { + return null + } + result.append('.') + result.append(namePos!!.lastComponent) + return result + } + else { + val nameComponent = namePos!!.lastComponent + namePos = namePos!!.parent + do { + if (namePos!!.lastComponent != prefix.lastComponent) { + return null + } + namePos = namePos!!.parent + prefix = prefix.parent!! + } + while (namePos != null) + + val result = StringBuilder() + result.append(nameComponent) + return result + } + } +} \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/StandaloneTypeBinding.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/StandaloneTypeBinding.java deleted file mode 100644 index 40fd24f40def..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/StandaloneTypeBinding.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.jetbrains.protocolReader; - -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jsonProtocol.ProtocolMetaModel; - -import java.io.IOException; -import java.util.List; - -interface StandaloneTypeBinding { - BoxableType getJavaType(); - - void generate() throws IOException; - - /** - * @return null if not direction-specific - */ - @Nullable - TypeData.Direction getDirection(); - - interface Target { - BoxableType resolve(ResolveContext context); - - interface ResolveContext { - BoxableType generateNestedObject(String shortName, String description, List properties); - } - } - - class PredefinedTarget implements Target { - private final BoxableType resolvedType; - - PredefinedTarget(BoxableType resolvedType) { - this.resolvedType = resolvedType; - } - - @Override - public BoxableType resolve(ResolveContext context) { - return resolvedType; - } - - public static final PredefinedTarget STRING = new PredefinedTarget(BoxableType.STRING); - public static final PredefinedTarget INT = new PredefinedTarget(BoxableType.INT); - public static final PredefinedTarget NUMBER = new PredefinedTarget(BoxableType.NUMBER); - public static final PredefinedTarget MAP = new PredefinedTarget(BoxableType.MAP); - } -} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/StandaloneTypeBinding.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/StandaloneTypeBinding.kt new file mode 100644 index 000000000000..ba0273aade32 --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/StandaloneTypeBinding.kt @@ -0,0 +1,35 @@ +package org.jetbrains.protocolReader + +trait StandaloneTypeBinding { + public fun getJavaType(): BoxableType + + public fun generate() + + /** + * @return null if not direction-specific + */ + public fun getDirection(): TypeData.Direction? + + public trait Target { + public fun resolve(context: ResolveContext): BoxableType + + public trait ResolveContext { + public fun generateNestedObject(shortName: String, description: String?, properties: List?): BoxableType + } + } + + public class PredefinedTarget(private val resolvedType: BoxableType) : Target { + + override fun resolve(context: Target.ResolveContext): BoxableType { + return resolvedType + } + + default object { + + public val STRING: PredefinedTarget = PredefinedTarget(BoxableType.STRING) + public val INT: PredefinedTarget = PredefinedTarget(BoxableType.INT) + public val NUMBER: PredefinedTarget = PredefinedTarget(BoxableType.NUMBER) + public val MAP: PredefinedTarget = PredefinedTarget(BoxableType.MAP) + } + } +} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TextOutConsumer.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TextOutConsumer.java deleted file mode 100644 index 44404ad895e1..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TextOutConsumer.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.jetbrains.protocolReader; - -public interface TextOutConsumer { - void append(TextOutput out); -} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TextOutConsumer.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TextOutConsumer.kt new file mode 100644 index 000000000000..2ef0ecc6461d --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TextOutConsumer.kt @@ -0,0 +1,5 @@ +package org.jetbrains.protocolReader + +public trait TextOutConsumer { + public fun append(out: TextOutput) +} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeData.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeData.java deleted file mode 100644 index 7fbc5f6c2cad..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeData.java +++ /dev/null @@ -1,176 +0,0 @@ -package org.jetbrains.protocolReader; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jsonProtocol.ProtocolMetaModel; - -class TypeData { - public static final StandaloneTypeBinding ANY = new StandaloneTypeBinding() { - @Override - public BoxableType getJavaType() { - return BoxableType.ANY_STRING; - } - - @Override - public void generate() { - } - - @Override - public Direction getDirection() { - return null; - } - }; - private final String name; - - private Input input; - private Output output; - - private ProtocolMetaModel.StandaloneType type; - private StandaloneTypeBinding commonBinding; - - TypeData(String name) { - this.name = name; - } - - void setType(@NotNull ProtocolMetaModel.StandaloneType type) { - this.type = type; - } - - Input getInput() { - if (input == null) { - input = new Input(); - } - return input; - } - - Output getOutput() { - if (output == null) { - output = new Output(); - } - return output; - } - - TypeRef get(Direction direction) { - return direction.get(this); - } - - void checkComplete() { - if (input != null) { - input.checkResolved(); - } - if (output != null) { - output.checkResolved(); - } - } - - enum Direction { - INPUT() { - @Override - TypeRef get(TypeData typeData) { - return typeData.getInput(); - } - }, - OUTPUT() { - @Override - TypeRef get(TypeData typeData) { - return typeData.getOutput(); - } - }; - abstract TypeRef get(TypeData typeData); - } - - abstract class TypeRef { - private StandaloneTypeBinding oneDirectionBinding; - - BoxableType resolve(@NotNull TypeMap typeMap, @NotNull DomainGenerator domainGenerator) { - if (commonBinding != null) { - return commonBinding.getJavaType(); - } - if (oneDirectionBinding != null) { - return oneDirectionBinding.getJavaType(); - } - StandaloneTypeBinding binding = resolveImpl(domainGenerator); - if (binding == null) { - return null; - } - - if (binding.getDirection() == null) { - commonBinding = binding; - } - else { - oneDirectionBinding = binding; - } - typeMap.addTypeToGenerate(binding); - return binding.getJavaType(); - } - - abstract StandaloneTypeBinding resolveImpl(DomainGenerator domainGenerator); - - void checkResolved() { - if (type == null && !(name.equals("int") || name.equals("any"))) { - throw new RuntimeException(); - } - } - } - - class Output extends TypeRef { - @Override - StandaloneTypeBinding resolveImpl(@NotNull DomainGenerator domainGenerator) { - if (type == null) { - if (name.equals("int")) { - return new StandaloneTypeBinding() { - @Override - public BoxableType getJavaType() { - return BoxableType.INT; - } - - @Override - public void generate() { - } - - @Override - public Direction getDirection() { - return null; - } - }; - } - else if (name.equals("any")) { - return ANY; - } - - throw new RuntimeException(); - } - return domainGenerator.createStandaloneOutputTypeBinding(type, name); - } - } - - class Input extends TypeRef { - @Override - StandaloneTypeBinding resolveImpl(@NotNull DomainGenerator domainGenerator) { - if (type == null) { - if (name.equals("int")) { - return new StandaloneTypeBinding() { - @Override - public BoxableType getJavaType() { - return BoxableType.INT; - } - - @Override - public void generate() { - } - - @Override - public Direction getDirection() { - return null; - } - }; - } - else if (name.equals("any")) { - return ANY; - } - - throw new RuntimeException(); - } - return domainGenerator.createStandaloneInputTypeBinding(type); - } - } -} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeData.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeData.kt new file mode 100644 index 000000000000..e971e9123f18 --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeData.kt @@ -0,0 +1,159 @@ +package org.jetbrains.protocolReader + +import org.jetbrains.protocolReader.TypeData + +class TypeData(private val name: String) { + private var input: Input? = null + private var output: Output? = null + + private var type: ProtocolMetaModel.StandaloneType? = null + private var commonBinding: StandaloneTypeBinding? = null + + fun setType(type: ProtocolMetaModel.StandaloneType) { + this.type = type + } + + fun getInput(): Input { + if (input == null) { + input = Input() + } + return input!! + } + + fun getOutput(): Output { + if (output == null) { + output = Output() + } + return output!! + } + + fun get(direction: Direction): TypeRef { + return direction.get(this) + } + + fun checkComplete() { + if (input != null) { + input!!.checkResolved() + } + if (output != null) { + output!!.checkResolved() + } + } + + abstract class Direction { + default object { + val INPUT = object : Direction() { + override fun get(typeData: TypeData) = typeData.getInput() + } + + val OUTPUT = object : Direction() { + override fun get(typeData: TypeData) = typeData.getOutput() + } + } + + abstract fun get(typeData: TypeData): TypeRef + } + + abstract inner class TypeRef { + private var oneDirectionBinding: StandaloneTypeBinding? = null + + fun resolve(typeMap: TypeMap, domainGenerator: DomainGenerator): BoxableType? { + if (commonBinding != null) { + return commonBinding!!.getJavaType() + } + if (oneDirectionBinding != null) { + return oneDirectionBinding!!.getJavaType() + } + val binding = resolveImpl(domainGenerator) + if (binding == null) { + return null + } + + if (binding.getDirection() == null) { + commonBinding = binding + } + else { + oneDirectionBinding = binding + } + typeMap.addTypeToGenerate(binding) + return binding.getJavaType() + } + + abstract fun resolveImpl(domainGenerator: DomainGenerator): StandaloneTypeBinding? + + fun checkResolved() { + if (type == null && !(name == "int" || name == "any")) { + throw RuntimeException() + } + } + } + + inner class Output : TypeRef() { + override fun resolveImpl(domainGenerator: DomainGenerator): StandaloneTypeBinding? { + if (type == null) { + if (name == "int") { + return object : StandaloneTypeBinding { + override fun getJavaType(): BoxableType { + return BoxableType.INT + } + + override fun generate() { + } + + override fun getDirection(): Direction? { + return null + } + } + } + else if (name == "any") { + return ANY + } + + throw RuntimeException() + } + return domainGenerator.createStandaloneOutputTypeBinding(type!!, name) + } + } + + inner class Input : TypeRef() { + override fun resolveImpl(domainGenerator: DomainGenerator): StandaloneTypeBinding? { + if (type == null) { + if (name == "int") { + return object : StandaloneTypeBinding { + override fun getJavaType(): BoxableType { + return BoxableType.INT + } + + override fun generate() { + } + + override fun getDirection(): Direction? { + return null + } + } + } + else if (name == "any") { + return ANY + } + + throw RuntimeException() + } + return domainGenerator.createStandaloneInputTypeBinding(type!!) + } + } + + default object { + public val ANY: StandaloneTypeBinding = object : StandaloneTypeBinding { + override fun getJavaType(): BoxableType { + return BoxableType.ANY_STRING + } + + override fun generate() { + } + + override fun getDirection(): Direction? { + return null + } + } + } +} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeDescriptor.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeDescriptor.java deleted file mode 100644 index d142e8bdf6d5..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeDescriptor.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.jetbrains.protocolReader; - -import org.jetbrains.annotations.NotNull; - -class TypeDescriptor { - private final BoxableType type; - private final boolean optional; - private final boolean nullable; - private final boolean asRawString; - - TypeDescriptor(@NotNull BoxableType type, boolean optional) { - this(type, optional, false, false); - } - - TypeDescriptor(@NotNull BoxableType type, boolean optional, boolean nullable, boolean asRawString) { - this.type = type; - this.optional = optional; - this.nullable = nullable; - this.asRawString = asRawString; - } - - boolean isNullable() { - return nullable; - } - - @NotNull - BoxableType getType() { - return type; - } - - void writeAnnotations(@NotNull TextOutput out) { - if (optional || asRawString) { - out.append("@org.jetbrains.jsonProtocol.JsonField("); - if (optional) { - out.append("optional=true"); - } - if (asRawString) { - if (optional) { - out.append(", "); - } - out.append("allowAnyPrimitiveValue=true"); - } - out.append(")").newLine(); - } - - if (isNullable()) { - out.append("@org.jetbrains.jsonProtocol.JsonNullable").newLine(); - } - } -} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeDescriptor.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeDescriptor.kt new file mode 100644 index 000000000000..7c64e34bf792 --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeDescriptor.kt @@ -0,0 +1,28 @@ +package org.jetbrains.protocolReader + +class TypeDescriptor(val type: BoxableType, private val optional: Boolean, private val nullable: Boolean = false, private val asRawString: Boolean = false) { + + fun isNullable(): Boolean { + return nullable + } + + fun writeAnnotations(out: TextOutput) { + if (optional || asRawString) { + out.append("@org.jetbrains.jsonProtocol.JsonField(") + if (optional) { + out.append("optional=true") + } + if (asRawString) { + if (optional) { + out.append(", ") + } + out.append("allowAnyPrimitiveValue=true") + } + out.append(")").newLine() + } + + if (isNullable()) { + out.append("@org.jetbrains.jsonProtocol.JsonNullable").newLine() + } + } +} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeMap.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeMap.java deleted file mode 100644 index a1d35b54cc0e..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeMap.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.jetbrains.protocolReader; - -import com.intellij.openapi.util.Pair; -import gnu.trove.THashMap; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * Keeps track of all referenced types. - * A type may be used and resolved (generated or hard-coded). - */ -class TypeMap { - private final Map, TypeData> map = new THashMap<>(); - private Map domainGeneratorMap; - private final List typesToGenerate = new ArrayList<>(); - - void setDomainGeneratorMap(Map domainGeneratorMap) { - this.domainGeneratorMap = domainGeneratorMap; - } - - @Nullable - BoxableType resolve(String domainName, String typeName, TypeData.Direction direction) { - DomainGenerator domainGenerator = domainGeneratorMap.get(domainName); - if (domainGenerator == null) { - throw new RuntimeException("Failed to find domain generator: " + domainName); - } - return getTypeData(domainName, typeName).get(direction).resolve(this, domainGenerator); - } - - void addTypeToGenerate(@NotNull StandaloneTypeBinding binding) { - typesToGenerate.add(binding); - } - - public void generateRequestedTypes() throws IOException { - // Size may grow during iteration. - //noinspection ForLoopReplaceableByForEach - for (int i = 0; i < typesToGenerate.size(); i++) { - typesToGenerate.get(i).generate(); - } - - for (TypeData typeData : map.values()) { - typeData.checkComplete(); - } - } - - @NotNull - TypeData getTypeData(@NotNull String domainName, @NotNull String typeName) { - Pair key = Pair.create(domainName, typeName); - TypeData result = map.get(key); - if (result == null) { - result = new TypeData(typeName); - map.put(key, result); - } - return result; - } -} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeMap.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeMap.kt new file mode 100644 index 000000000000..2c311746b66e --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeMap.kt @@ -0,0 +1,50 @@ +package org.jetbrains.protocolReader + +/** + * Keeps track of all referenced types. + * A type may be used and resolved (generated or hard-coded). + */ +class TypeMap { + private val map = THashMap, TypeData>() + private var domainGeneratorMap: Map? = null + private val typesToGenerate = ArrayList() + + fun setDomainGeneratorMap(domainGeneratorMap: Map) { + this.domainGeneratorMap = domainGeneratorMap + } + + fun resolve(domainName: String, typeName: String, direction: TypeData.Direction): BoxableType? { + val domainGenerator = domainGeneratorMap!!.get(domainName) + if (domainGenerator == null) { + throw RuntimeException("Failed to find domain generator: " + domainName) + } + return getTypeData(domainName, typeName).get(direction).resolve(this, domainGenerator) + } + + fun addTypeToGenerate(binding: StandaloneTypeBinding) { + typesToGenerate.add(binding) + } + + throws(javaClass()) + public fun generateRequestedTypes() { + // Size may grow during iteration. + //noinspection ForLoopReplaceableByForEach + for (i in typesToGenerate.indices) { + typesToGenerate.get(i).generate() + } + + for (typeData in map.values()) { + typeData.checkComplete() + } + } + + fun getTypeData(domainName: String, typeName: String): TypeData { + val key = Pair.create(domainName, typeName) + var result: TypeData? = map.get(key) + if (result == null) { + result = TypeData(typeName) + map.put(key, result) + } + return result!! + } +} diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeVisitor.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeVisitor.java deleted file mode 100644 index 0aae6cc8179a..000000000000 --- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeVisitor.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.jetbrains.protocolReader; - -import org.jetbrains.jsonProtocol.ProtocolMetaModel; - -import java.util.List; - -interface TypeVisitor { - R visitRef(String refName); - - R visitBoolean(); - - R visitEnum(List enumConstants); - - R visitString(); - - R visitInteger(); - - R visitNumber(); - - R visitArray(ProtocolMetaModel.ArrayItemType items); - - R visitObject(List properties); - - R visitMap(); - - R visitUnknown(); -} \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeVisitor.kt b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeVisitor.kt new file mode 100644 index 000000000000..ca53230e8d18 --- /dev/null +++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeVisitor.kt @@ -0,0 +1,23 @@ +package org.jetbrains.protocolReader + +trait TypeVisitor { + public fun visitRef(refName: String): R + + public fun visitBoolean(): R + + public fun visitEnum(enumConstants: List): R + + public fun visitString(): R + + public fun visitInteger(): R + + public fun visitNumber(): R + + public fun visitArray(items: ProtocolMetaModel.ArrayItemType): R + + public fun visitObject(properties: List?): R + + public fun visitMap(): R + + public fun visitUnknown(): R +} \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonOptionalField.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonOptionalField.java index 92c9cd978700..545037e01315 100644 --- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonOptionalField.java +++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonOptionalField.java @@ -1,7 +1,6 @@ // Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - package org.jetbrains.jsonProtocol; import java.lang.annotation.ElementType; diff --git a/platform/script-debugger/protocol/protocol-reader/protocol-reader.iml b/platform/script-debugger/protocol/protocol-reader/protocol-reader.iml index 1eded93d37e9..7c6275fd1a04 100644 --- a/platform/script-debugger/protocol/protocol-reader/protocol-reader.iml +++ b/platform/script-debugger/protocol/protocol-reader/protocol-reader.iml @@ -1,6 +1,6 @@ - + diff --git a/platform/script-debugger/protocol/protocol-reader/src/FieldProcessor.kt b/platform/script-debugger/protocol/protocol-reader/src/FieldProcessor.kt index 2b813edcabdf..1df6c60dcf3e 100644 --- a/platform/script-debugger/protocol/protocol-reader/src/FieldProcessor.kt +++ b/platform/script-debugger/protocol/protocol-reader/src/FieldProcessor.kt @@ -4,10 +4,11 @@ import gnu.trove.THashSet import org.jetbrains.jsonProtocol.JsonField import org.jetbrains.jsonProtocol.JsonOptionalField import org.jetbrains.jsonProtocol.JsonSubtypeCasting - import java.lang.reflect.Method import java.lang.reflect.ParameterizedType -import java.util.* +import java.util.ArrayList +import java.util.Arrays +import java.util.LinkedHashMap class FieldProcessor(private val reader: InterfaceReader, typeClass: Class<*>) { val fieldLoaders = ArrayList() @@ -15,10 +16,10 @@ class FieldProcessor(private val reader: InterfaceReader, typeClass: Class<*>) { val volatileFields = ArrayList() var lazyRead: Boolean = false - { + init { val methods = typeClass.getMethods() // todo sort by source location - Arrays.sort(methods, {(o1, o2) -> o1.getName().compareTo(o2.getName())}) + Arrays.sort(methods, {(o1, o2) -> o1.getName().compareTo(o2.getName()) }) val skippedNames = THashSet() for (method in methods) { diff --git a/platform/script-debugger/protocol/protocol-reader/src/GlobalScope.kt b/platform/script-debugger/protocol/protocol-reader/src/GlobalScope.kt index 733e5ecdb03d..ddb05e0ff13c 100644 --- a/platform/script-debugger/protocol/protocol-reader/src/GlobalScope.kt +++ b/platform/script-debugger/protocol/protocol-reader/src/GlobalScope.kt @@ -40,7 +40,7 @@ private class State(typeWriters: Collection>, private val basePack private val typesWithFactories = THashSet>() val typesWithFactoriesList = ArrayList>(); - { + init { var uniqueCode = 0 val result = THashMap, String>(typeWriters.size()) for (handler in typeWriters) { diff --git a/platform/script-debugger/protocol/protocol-reader/src/InterfaceReader.kt b/platform/script-debugger/protocol/protocol-reader/src/InterfaceReader.kt index 053c68b2ba05..50fef016331b 100644 --- a/platform/script-debugger/protocol/protocol-reader/src/InterfaceReader.kt +++ b/platform/script-debugger/protocol/protocol-reader/src/InterfaceReader.kt @@ -1,16 +1,17 @@ package org.jetbrains.protocolReader +import gnu.trove.THashSet import org.jetbrains.io.JsonReaderEx import org.jetbrains.jsonProtocol.JsonField +import org.jetbrains.jsonProtocol.JsonOptionalField import org.jetbrains.jsonProtocol.JsonSubtype import org.jetbrains.jsonProtocol.StringIntPair - import java.lang.reflect.Method import java.lang.reflect.ParameterizedType import java.lang.reflect.Type import java.lang.reflect.WildcardType -import java.util.* -import gnu.trove.* +import java.util.ArrayList +import java.util.LinkedHashMap fun InterfaceReader(protocolInterfaces: Array>): InterfaceReader { val __ = InterfaceReader(LinkedHashMap, TypeWriter<*>>(protocolInterfaces.size())) @@ -130,6 +131,9 @@ class InterfaceReader(val typeToTypeHandler: LinkedHashMap, TypeWriter< if (jsonField != null && jsonField.allowAnyPrimitiveValue()) { return RAW_STRING_PARSER } + else if ((jsonField != null && jsonField.optional()) || method.getAnnotation(javaClass()) != null) { + return NULLABLE_STRING_PARSER + } } return STRING_PARSER } @@ -220,6 +224,7 @@ class InterfaceReader(val typeToTypeHandler: LinkedHashMap, TypeWriter< private val NUMBER_PARSER = PrimitiveValueReader("double") private val STRING_PARSER = PrimitiveValueReader("String") + private val NULLABLE_STRING_PARSER = PrimitiveValueReader(className = "String", nullable = true) private val RAW_STRING_PARSER = PrimitiveValueReader("String", null, true) private val RAW_STRING_OR_MAP_PARSER = object : PrimitiveValueReader("Object", null, true) { diff --git a/platform/script-debugger/protocol/protocol-reader/src/PrimitiveValueReader.kt b/platform/script-debugger/protocol/protocol-reader/src/PrimitiveValueReader.kt index f091e1c2880d..7f36b0f6a37d 100644 --- a/platform/script-debugger/protocol/protocol-reader/src/PrimitiveValueReader.kt +++ b/platform/script-debugger/protocol/protocol-reader/src/PrimitiveValueReader.kt @@ -1,18 +1,9 @@ package org.jetbrains.protocolReader - -fun PrimitiveValueReader(name: String): PrimitiveValueReader { - return PrimitiveValueReader(name, null, false) -} - -fun PrimitiveValueReader(name: String, defaultValue: String): PrimitiveValueReader { - return PrimitiveValueReader(name, defaultValue, false) -} - -open class PrimitiveValueReader(private val className: String, val defaultValue: String?, private val asRawString: Boolean) : ValueReader() { +open class PrimitiveValueReader(private val className: String, val defaultValue: String? = null, private val asRawString: Boolean = false, private val nullable: Boolean = false) : ValueReader() { private val readPostfix: String - { + init { if (Character.isLowerCase(className.charAt(0))) { readPostfix = Character.toUpperCase(className.charAt(0)) + className.substring(1) } @@ -29,7 +20,11 @@ open class PrimitiveValueReader(private val className: String, val defaultValue: } else { addReaderParameter(subtyping, out) - out.append(".next").append(readPostfix).append("()") + out.append(".next"); + if (nullable) { + out.append("Nullable"); + } + out.append(readPostfix).append("()") //beginReadCall(readPostfix, subtyping, out, name); } } diff --git a/platform/script-debugger/protocol/protocol-reader/src/ReaderGenerator.kt b/platform/script-debugger/protocol/protocol-reader/src/ReaderGenerator.kt index ca030a5270e1..83fffd1b5112 100644 --- a/platform/script-debugger/protocol/protocol-reader/src/ReaderGenerator.kt +++ b/platform/script-debugger/protocol/protocol-reader/src/ReaderGenerator.kt @@ -1,13 +1,12 @@ package org.jetbrains.protocolReader import gnu.trove.THashMap - import java.io.File import java.nio.file.FileSystems -import java.util.* +import java.util.HashMap +import java.util.LinkedHashMap public class ReaderGenerator { - public class GenerateConfiguration(val packageName: String, val className: String, readerRootClass: Class, protocolInterfaces: Array>, basePackagesMap: Map, String>? = null) { val basePackagesMap: Collection, String>> diff --git a/platform/script-debugger/protocol/schema-reader-generator/schema-reader-generator.iml b/platform/script-debugger/protocol/schema-reader-generator/schema-reader-generator.iml index 7c859fb93668..a2a9f7558e93 100644 --- a/platform/script-debugger/protocol/schema-reader-generator/schema-reader-generator.iml +++ b/platform/script-debugger/protocol/schema-reader-generator/schema-reader-generator.iml @@ -1,6 +1,6 @@ - + @@ -9,6 +9,7 @@ + + - - + \ No newline at end of file diff --git a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ItemDescriptor.java b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ItemDescriptor.java deleted file mode 100644 index d6f5afcfbe27..000000000000 --- a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ItemDescriptor.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.jetbrains.jsonProtocol; - -import java.util.List; - -public interface ItemDescriptor { - String description(); - - String type(); - - List getEnum(); - - ProtocolMetaModel.ArrayItemType items(); - - interface Named extends Referenceable { - String name(); - - @JsonOptionalField - String shortName(); - - boolean optional(); - } - - interface Referenceable extends ItemDescriptor { - String ref(); - } - - interface Type extends ItemDescriptor { - List properties(); - } -} \ No newline at end of file diff --git a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ItemDescriptor.kt b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ItemDescriptor.kt new file mode 100644 index 000000000000..c32c392a0b77 --- /dev/null +++ b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ItemDescriptor.kt @@ -0,0 +1,28 @@ +package org.jetbrains.jsonProtocol + +public trait ItemDescriptor { + public fun description(): String? + + public fun type(): String + + public fun getEnum(): List? + + public fun items(): ProtocolMetaModel.ArrayItemType + + public trait Named : Referenceable { + public fun name(): String + + JsonOptionalField + public fun shortName(): String? + + public fun optional(): Boolean + } + + public trait Referenceable : ItemDescriptor { + public fun ref(): String + } + + public trait Type : ItemDescriptor { + public fun properties(): List? + } +} \ No newline at end of file diff --git a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolMetaModel.java b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolMetaModel.java deleted file mode 100644 index a4aeeec15d37..000000000000 --- a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolMetaModel.java +++ /dev/null @@ -1,223 +0,0 @@ -package org.jetbrains.jsonProtocol; - -import java.util.List; - -/** - * Defines schema of WIP metamodel defined in http://svn.webkit.org/repository/webkit/trunk/Source/WebCore/inspector/Inspector.json - */ -public interface ProtocolMetaModel { - @JsonType - interface Root { - @JsonOptionalField - Version version(); - - List domains(); - } - - @JsonType - interface Version { - String major(); - String minor(); - } - - @JsonType - interface Domain { - String domain(); - - @JsonOptionalField - List types(); - - List commands(); - - @JsonOptionalField - List events(); - - @JsonOptionalField - String description(); - - @JsonOptionalField - boolean hidden(); - } - - @JsonType - interface Command { - String name(); - - @JsonOptionalField - List parameters(); - - @JsonOptionalField - List returns(); - - @JsonOptionalField - String description(); - - @JsonOptionalField - boolean hidden(); - - @JsonOptionalField - boolean async(); - } - - @JsonType - interface Parameter extends ItemDescriptor.Named { - @Override - String name(); - - @Override - @JsonOptionalField - String shortName(); - - @Override - @JsonOptionalField - String type(); - - @Override - @JsonOptionalField - ArrayItemType items(); - - @Override - @JsonField(jsonLiteralName = "enum") - @JsonOptionalField - List getEnum(); - - @Override - @JsonOptionalField - @JsonField(jsonLiteralName = "$ref") - String ref(); - - @Override - @JsonOptionalField - boolean optional(); - - @Override - @JsonOptionalField - String description(); - - @JsonOptionalField - boolean hidden(); - } - - @JsonType - interface Event { - String name(); - - @JsonOptionalField - List parameters(); - - @JsonOptionalField - String description(); - - @JsonOptionalField - boolean hidden(); - } - - @JsonType - interface StandaloneType extends ItemDescriptor.Type { - String id(); - - @Override - @JsonOptionalField - String description(); - - @Override - String type(); - - @JsonOptionalField - boolean hidden(); - - @Override - @JsonOptionalField - List properties(); - - @Override - @JsonField(jsonLiteralName = "enum") - @JsonOptionalField - List getEnum(); - - @Override - @JsonOptionalField - ArrayItemType items(); - } - - - @JsonType - interface ArrayItemType extends ItemDescriptor.Type, ItemDescriptor.Referenceable { - @Override - @JsonOptionalField - String description(); - - @JsonOptionalField - boolean optional(); - - @Override - @JsonOptionalField - String type(); - - @Override - @JsonOptionalField - ArrayItemType items(); - - @Override - @JsonField(jsonLiteralName = "$ref") - @JsonOptionalField - String ref(); - - @Override - @JsonField(jsonLiteralName = "enum") - @JsonOptionalField - List getEnum(); - - @Override - @JsonOptionalField - List properties(); - } - - @JsonType - interface ObjectProperty extends ItemDescriptor.Named { - @Override - String name(); - - @Override - @JsonOptionalField - String shortName(); - - @Override - @JsonOptionalField - String description(); - - @Override - @JsonOptionalField - boolean optional(); - - @Override - @JsonOptionalField - String type(); - - @Override - @JsonOptionalField - ArrayItemType items(); - - @Override - @JsonField(jsonLiteralName = "$ref") - @JsonOptionalField - String ref(); - - @Override - @JsonField(jsonLiteralName = "enum") - @JsonOptionalField - List getEnum(); - - @JsonOptionalField - boolean hidden(); - } - - String STRING_TYPE = "string"; - String INTEGER_TYPE = "integer"; - String NUMBER_TYPE = "number"; - String BOOLEAN_TYPE = "boolean"; - String OBJECT_TYPE = "object"; - String ARRAY_TYPE = "array"; - String UNKNOWN_TYPE = "unknown"; - String ANY_TYPE = "any"; -} diff --git a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolMetaModel.kt b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolMetaModel.kt new file mode 100644 index 000000000000..6377affbf41c --- /dev/null +++ b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolMetaModel.kt @@ -0,0 +1,196 @@ +package org.jetbrains.jsonProtocol + +/** + * Defines schema of WIP metamodel defined in http://svn.webkit.org/repository/webkit/trunk/Source/WebCore/inspector/Inspector.json + */ +public trait ProtocolMetaModel { + JsonType + public trait Root { + JsonOptionalField + public fun version(): Version + + public fun domains(): List + } + + JsonType + public trait Version { + public fun major(): String + public fun minor(): String + } + + JsonType + public trait Domain { + public fun domain(): String + + JsonOptionalField + public fun types(): List? + + public fun commands(): List + + JsonOptionalField + public fun events(): List? + + JsonOptionalField + public fun description(): String + + JsonOptionalField + public fun hidden(): Boolean + } + + JsonType + public trait Command { + public fun name(): String + + JsonOptionalField + public fun parameters(): List? + + JsonOptionalField + public fun returns(): List? + + JsonOptionalField + public fun description(): String + + JsonOptionalField + public fun hidden(): Boolean + + JsonOptionalField + public fun async(): Boolean + } + + JsonType + public trait Parameter : ItemDescriptor.Named { + override fun name(): String + + JsonOptionalField + override fun shortName(): String + + JsonOptionalField + override fun type(): String + + JsonOptionalField + override fun items(): ArrayItemType + + JsonField(name = "enum") + JsonOptionalField + override fun getEnum(): List + + JsonOptionalField + JsonField(name = "\$ref") + override fun ref(): String + + JsonOptionalField + override fun optional(): Boolean + + JsonOptionalField + override fun description(): String + + JsonOptionalField + public fun hidden(): Boolean + } + + JsonType + public trait Event { + public fun name(): String + + JsonOptionalField + public fun parameters(): List + + JsonOptionalField + public fun description(): String + + JsonOptionalField + public fun hidden(): Boolean + } + + JsonType + public trait StandaloneType : ItemDescriptor.Type { + public fun id(): String + + JsonOptionalField + override fun description(): String? + + override fun type(): String + + JsonOptionalField + public fun hidden(): Boolean + + JsonOptionalField + override fun properties(): List + + JsonField(name = "enum") + JsonOptionalField + override fun getEnum(): List + + JsonOptionalField + override fun items(): ArrayItemType + } + + + JsonType + public trait ArrayItemType : ItemDescriptor.Type, ItemDescriptor.Referenceable { + JsonOptionalField + override fun description(): String + + JsonOptionalField + public fun optional(): Boolean + + JsonOptionalField + override fun type(): String + + JsonOptionalField + override fun items(): ArrayItemType + + JsonField(name = "\$ref") + JsonOptionalField + override fun ref(): String + + JsonField(name = "enum") + JsonOptionalField + override fun getEnum(): List + + JsonOptionalField + override fun properties(): List + } + + JsonType + public trait ObjectProperty : ItemDescriptor.Named { + override fun name(): String + + JsonOptionalField + override fun shortName(): String + + JsonOptionalField + override fun description(): String + + JsonOptionalField + override fun optional(): Boolean + + JsonOptionalField + override fun type(): String + + JsonOptionalField + override fun items(): ArrayItemType + + JsonField(name = "\$ref") + JsonOptionalField + override fun ref(): String + + JsonField(name = "enum") + JsonOptionalField + override fun getEnum(): List + + JsonOptionalField + public fun hidden(): Boolean + } + + default object { + public val STRING_TYPE: String = "string" + public val INTEGER_TYPE: String = "integer" + public val NUMBER_TYPE: String = "number" + public val BOOLEAN_TYPE: String = "boolean" + public val OBJECT_TYPE: String = "object" + public val ARRAY_TYPE: String = "array" + public val UNKNOWN_TYPE: String = "unknown" + public val ANY_TYPE: String = "any" + } +} diff --git a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolSchemaReader.java b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolSchemaReader.java deleted file mode 100644 index aafe735409fd..000000000000 --- a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolSchemaReader.java +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.jetbrains.jsonProtocol; - -import org.jetbrains.io.JsonReaderEx; -import org.jetbrains.jsonProtocol.ProtocolMetaModel.Root; - -import java.io.IOException; - -public interface ProtocolSchemaReader { - @JsonParseMethod - Root parseRoot(JsonReaderEx reader) throws IOException; -} \ No newline at end of file diff --git a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolSchemaReader.kt b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolSchemaReader.kt new file mode 100644 index 000000000000..53c6685e1890 --- /dev/null +++ b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolSchemaReader.kt @@ -0,0 +1,12 @@ +package org.jetbrains.jsonProtocol + +import org.jetbrains.io.JsonReaderEx +import org.jetbrains.jsonProtocol.ProtocolMetaModel.Root + +import java.io.IOException + +public trait ProtocolSchemaReader { + JsonParseMethod + throws(javaClass()) + public fun parseRoot(reader: JsonReaderEx): Root +} \ No newline at end of file diff --git a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/SchemaReaderGenerator.java b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/SchemaReaderGenerator.java deleted file mode 100644 index 1220ffa0cd91..000000000000 --- a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/SchemaReaderGenerator.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.jetbrains.jsonProtocol; - -import org.jetbrains.protocolReader.ReaderGenerator; - -import java.io.IOException; - -public class SchemaReaderGenerator { - public static void main(String[] args) throws IOException { - ReaderGenerator.generate(args, new ReaderGenerator.GenerateConfiguration<>("org.jetbrains.jsonProtocol", "ProtocolSchemaReaderImpl", ProtocolSchemaReader.class, ProtocolMetaModel.class.getDeclaredClasses())); - } -} \ No newline at end of file diff --git a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/SchemaReaderGenerator.kt b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/SchemaReaderGenerator.kt new file mode 100644 index 000000000000..89d1db391f97 --- /dev/null +++ b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/SchemaReaderGenerator.kt @@ -0,0 +1,5 @@ +package org.jetbrains.jsonProtocol + +import org.jetbrains.protocolReader.ReaderGenerator + +fun main(args: Array) = ReaderGenerator.generate(args, ReaderGenerator.GenerateConfiguration("org.jetbrains.jsonProtocol", "ProtocolSchemaReaderImpl", javaClass(), javaClass().getDeclaredClasses())) \ No newline at end of file diff --git a/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java b/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java index c5931f98df10..cf6b81c36cd6 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java +++ b/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java @@ -15,6 +15,7 @@ */ package git4idea.commands; +import com.intellij.ide.passwordSafe.MasterPasswordUnavailableException; import com.intellij.ide.passwordSafe.PasswordSafe; import com.intellij.ide.passwordSafe.PasswordSafeException; import com.intellij.ide.passwordSafe.impl.PasswordSafeImpl; @@ -169,6 +170,8 @@ class GitHttpGuiAuthenticator implements GitHttpAuthenticator { passwordSafe.getMasterKeyProvider().storePassword(myProject, PASS_REQUESTER, myPasswordKey, myPassword); } } + catch (MasterPasswordUnavailableException ignored) { + } catch (PasswordSafeException e) { LOG.error("Couldn't remember password for " + myPasswordKey, e); } diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubCreatePullRequestWorker.java b/plugins/github/src/org/jetbrains/plugins/github/GithubCreatePullRequestWorker.java index 8a818cac09b7..b65e7f204ef1 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubCreatePullRequestWorker.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubCreatePullRequestWorker.java @@ -503,13 +503,15 @@ public class GithubCreatePullRequestWorker { String targetBranchName = "'" + fork.getRemoteName() + "/" + branch.getRemoteName() + "'"; if (info.getInfo().getBranchToHeadCommits(myGitRepository).isEmpty()) { return GithubNotifications - .showYesNoDialog(myProject, "Do you want to proceed anyway?", - "Empty pull request: the branch " + localBranchName + " is fully merged to the branch " + targetBranchName); + .showYesNoDialog(myProject, "Empty Pull Request", + "The branch " + localBranchName + " is fully merged to the branch " + targetBranchName + '\n' + + "Do you want to proceed anyway?"); } if (!info.getInfo().getHeadToBranchCommits(myGitRepository).isEmpty()) { return GithubNotifications - .showYesNoDialog(myProject, "Do you want to proceed anyway?", - "The branch " + targetBranchName + " is not fully merged to the branch " + localBranchName); + .showYesNoDialog(myProject, "Target Branch Is Not Fully Merged", + "The branch " + targetBranchName + " is not fully merged to the branch " + localBranchName + '\n' + + "Do you want to proceed anyway?"); } return true; diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java index 537a580775c8..dd19041da102 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java @@ -15,6 +15,7 @@ */ package org.jetbrains.plugins.github; +import com.intellij.ide.BrowserUtil; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; @@ -23,6 +24,7 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.Splitter; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Ref; @@ -33,6 +35,7 @@ import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vcs.changes.ui.SelectFilesDialog; import com.intellij.openapi.vcs.ui.CommitMessage; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.Function; import com.intellij.util.ThrowableConvertor; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashSet; @@ -44,6 +47,7 @@ import git4idea.actions.BasicAction; import git4idea.actions.GitInit; import git4idea.commands.*; import git4idea.i18n.GitBundle; +import git4idea.repo.GitRemote; import git4idea.repo.GitRepository; import git4idea.repo.GitRepositoryManager; import git4idea.util.GitFileUtils; @@ -62,9 +66,7 @@ import org.jetbrains.plugins.github.util.GithubUtil; import javax.swing.*; import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; +import java.util.*; import static org.jetbrains.plugins.github.util.GithubUtil.setVisibleEnabled; @@ -119,13 +121,19 @@ public class GithubShareAction extends DumbAwareAction { final GithubAuthDataHolder authHolder = GithubAuthDataHolder.createFromSettings(); // check for existing git repo - boolean externalRemoteDetected = false; + Set existingRemotes = Collections.emptySet(); if (gitDetected) { final String githubRemote = GithubUtil.findGithubRemoteUrl(gitRepository); if (githubRemote != null) { if (!checkExistingRemote(project, authHolder, githubRemote)) return; } - externalRemoteDetected = !gitRepository.getRemotes().isEmpty(); + + existingRemotes = ContainerUtil.map2Set(gitRepository.getRemotes(), new Function() { + @Override + public String fun(GitRemote remote) { + return remote.getName(); + } + }); } // get available GitHub repos with modal progress @@ -136,7 +144,7 @@ public class GithubShareAction extends DumbAwareAction { // Show dialog (window) final GithubShareDialog shareDialog = - new GithubShareDialog(project, githubInfo.getRepositoryNames(), githubInfo.getUser().canCreatePrivateRepo()); + new GithubShareDialog(project, githubInfo.getRepositoryNames(), existingRemotes, githubInfo.getUser().canCreatePrivateRepo()); DialogManager.show(shareDialog); if (!shareDialog.isOK()) { return; @@ -144,9 +152,8 @@ public class GithubShareAction extends DumbAwareAction { final boolean isPrivate = shareDialog.isPrivate(); final String name = shareDialog.getRepositoryName(); final String description = shareDialog.getDescription(); + final String remoteName = shareDialog.getRemoteName(); - // finish the job in background - final boolean finalExternalRemoteDetected = externalRemoteDetected; new Task.Backgroundable(project, "Sharing project on GitHub...") { @Override public void run(@NotNull ProgressIndicator indicator) { @@ -178,7 +185,6 @@ public class GithubShareAction extends DumbAwareAction { } final String remoteUrl = GithubUrlUtil.getCloneUrl(githubInfo.getUser().getLogin(), name); - final String remoteName = finalExternalRemoteDetected ? "github" : "origin"; //git remote add origin git@github.com:login/name.git LOG.info("Adding GitHub as a remote host"); @@ -210,7 +216,7 @@ public class GithubShareAction extends DumbAwareAction { final GithubFullPath path = GithubUrlUtil.getUserAndRepositoryFromRemoteUrl(remote); if (path == null) { return GithubNotifications.showYesNoDialog(project, - "Project is already on GitHub", + "Project Is Already on GitHub", "Can't connect to repository from configured remote. You could want to check .git config.\n" + "Do you want to proceed anyway?"); } @@ -231,22 +237,30 @@ public class GithubShareAction extends DumbAwareAction { }); } }); - GithubNotifications.showInfoURL(project, "Project is already on GitHub", "GitHub", repo.getHtmlUrl()); + int result = Messages.showDialog(project, + "Successfully connected to " + repo.getHtmlUrl() + ".\n" + + "Do you want to proceed anyway?", + "Project Is Already on GitHub", + new String[]{"Continue", "Open in Browser", Messages.CANCEL_BUTTON}, 2, Messages.getQuestionIcon()); + if (result == 0) return true; + if (result == 1) { + BrowserUtil.browse(repo.getHtmlUrl()); + } return false; } catch (GithubStatusCodeException e) { if (e.getStatusCode() == HttpStatus.SC_NOT_FOUND) { return GithubNotifications.showYesNoDialog(project, - "Project is already on GitHub", + "Project Is Already on GitHub", "Can't connect to repository from configured remote. You could want to check .git config.\n" + "Do you want to proceed anyway?"); } - GithubNotifications.showErrorDialog(project, "Failed to connect to GitHub", e); + GithubNotifications.showErrorDialog(project, "Failed to Connect to GitHub", e); return false; } catch (IOException e) { - GithubNotifications.showErrorDialog(project, "Failed to connect to GitHub", e); + GithubNotifications.showErrorDialog(project, "Failed to Connect to GitHub", e); return false; } } @@ -278,7 +292,7 @@ public class GithubShareAction extends DumbAwareAction { }); } catch (IOException e) { - GithubNotifications.showErrorDialog(project, "Failed to connect to GitHub", e); + GithubNotifications.showErrorDialog(project, "Failed to Connect to GitHub", e); return null; } } diff --git a/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubCheckoutProvider.java b/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubCheckoutProvider.java index 1364e4ad7c66..260a7b36e88b 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubCheckoutProvider.java +++ b/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubCheckoutProvider.java @@ -33,6 +33,7 @@ import org.jetbrains.plugins.github.api.GithubConnection; import org.jetbrains.plugins.github.api.GithubRepo; import org.jetbrains.plugins.github.util.GithubAuthDataHolder; import org.jetbrains.plugins.github.util.GithubNotifications; +import org.jetbrains.plugins.github.util.GithubUrlUtil; import org.jetbrains.plugins.github.util.GithubUtil; import java.io.File; @@ -88,7 +89,7 @@ public class GithubCheckoutProvider implements CheckoutProvider { // Add predefined repositories to history dialog.prependToHistory("-----------------------------------------------"); for (int i = availableRepos.size() - 1; i >= 0; i--) { - dialog.prependToHistory(availableRepos.get(i).getCloneUrl()); + dialog.prependToHistory(GithubUrlUtil.getCloneUrl(availableRepos.get(i).getFullPath())); } if (!dialog.showAndGet()) { return; diff --git a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java index e3e8daabb56a..d826763e1667 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java +++ b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java @@ -139,7 +139,7 @@ public class GithubRepositoryEditor extends BaseRepositoryEditor

- + @@ -28,7 +28,7 @@ - + @@ -167,7 +167,7 @@ - + @@ -204,7 +204,15 @@ - + + + + + + + + + diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java index f9d32e171af4..7b9d1368c487 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java @@ -25,6 +25,7 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.HyperlinkAdapter; +import com.intellij.ui.components.JBCheckBox; import com.intellij.ui.components.JBLabel; import com.intellij.util.ThrowableConvertor; import org.jetbrains.annotations.NotNull; @@ -33,7 +34,6 @@ import org.jetbrains.plugins.github.api.GithubApiUtil; import org.jetbrains.plugins.github.api.GithubConnection; import org.jetbrains.plugins.github.api.GithubUser; import org.jetbrains.plugins.github.exceptions.GithubAuthenticationException; -import org.jetbrains.plugins.github.exceptions.GithubOperationCanceledException; import org.jetbrains.plugins.github.util.*; import javax.swing.*; @@ -71,6 +71,7 @@ public class GithubSettingsPanel { private JBLabel myAuthTypeLabel; private JSpinner myTimeoutSpinner; private JButton myCreateTokenButton; + private JBCheckBox myCloneUsingSshCheckBox; private boolean myCredentialsModified; @@ -145,7 +146,7 @@ public class GithubSettingsPanel { ); } catch (IOException ex) { - GithubNotifications.showErrorDialog(myPane, "Can't create API token", ex); + GithubNotifications.showErrorDialog(myPane, "Can't Create API Token", ex); } } }); @@ -286,6 +287,7 @@ public class GithubSettingsPanel { setPassword(mySettings.isAuthConfigured() ? DEFAULT_PASSWORD_TEXT : ""); setAuthType(mySettings.getAuthType()); setConnectionTimeout(mySettings.getConnectionTimeout()); + myCloneUsingSshCheckBox.setSelected(mySettings.isCloneGitUsingSsh()); resetCredentialsModification(); } @@ -294,12 +296,15 @@ public class GithubSettingsPanel { mySettings.setAuthData(getAuthData(), true); } mySettings.setConnectionTimeout(getConnectionTimeout()); + mySettings.setCloneGitUsingSsh(myCloneUsingSshCheckBox.isSelected()); resetCredentialsModification(); } public boolean isModified() { - return myCredentialsModified || !Comparing.equal(mySettings.getHost(), getHost()) || - !Comparing.equal(mySettings.getConnectionTimeout(), getConnectionTimeout()); + return myCredentialsModified || + !Comparing.equal(mySettings.getHost(), getHost()) || + !Comparing.equal(mySettings.getConnectionTimeout(), getConnectionTimeout()) || + !Comparing.equal(mySettings.isCloneGitUsingSsh(), myCloneUsingSshCheckBox.isSelected()); } public void resetCredentialsModification() { diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubShareDialog.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubShareDialog.java index 3b464b2828ac..a6a537faf74f 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubShareDialog.java +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubShareDialog.java @@ -18,15 +18,18 @@ public class GithubShareDialog extends DialogWrapper { private static final Pattern GITHUB_REPO_PATTERN = Pattern.compile("[a-zA-Z0-9_.-]+"); private final GithubSharePanel myGithubSharePanel; private final Set myAvailableNames; + private final Set myAvailableRemotes; - public GithubShareDialog(final Project project, final Set availableNames, final boolean privateRepoAllowed) { + public GithubShareDialog(Project project, Set availableNames, Set availableRemotes, boolean privateRepoAllowed) { super(project); myAvailableNames = availableNames; + myAvailableRemotes = availableRemotes; myGithubSharePanel = new GithubSharePanel(this); init(); setTitle("Share Project On GitHub"); setOKButtonText("Share"); myGithubSharePanel.setRepositoryName(project.getName()); + myGithubSharePanel.setRemoteName(availableRemotes.isEmpty() ? "origin" : "github"); myGithubSharePanel.setPrivateRepoAvailable(privateRepoAllowed); init(); updateOkButton(); @@ -53,7 +56,8 @@ public class GithubShareDialog extends DialogWrapper { } public void updateOkButton() { - final String repositoryName = getRepositoryName(); + String repositoryName = getRepositoryName(); + String remoteName = getRemoteName(); if (StringUtil.isEmpty(repositoryName)){ setErrorText("No repository name selected"); setOKActionEnabled(false); @@ -64,6 +68,11 @@ public class GithubShareDialog extends DialogWrapper { setOKActionEnabled(false); return; } + if (myAvailableRemotes.contains(remoteName)) { + setErrorText("Remote with selected name already exists"); + setOKActionEnabled(false); + return; + } if (!GITHUB_REPO_PATTERN.matcher(repositoryName).matches()){ setErrorText("Invalid repository name. Name should consist of letters, numbers, dashes, dots and underscores"); setOKActionEnabled(false); @@ -85,6 +94,10 @@ public class GithubShareDialog extends DialogWrapper { return myGithubSharePanel.getDescription(); } + public String getRemoteName() { + return myGithubSharePanel.getRemoteName(); + } + @TestOnly public void testSetRepositoryName(@NotNull String name) { myGithubSharePanel.setRepositoryName(name); diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSharePanel.form b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSharePanel.form index 31fa28e4c1c9..f8493892389d 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSharePanel.form +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSharePanel.form @@ -1,9 +1,9 @@ - + - + @@ -26,7 +26,7 @@ - + @@ -41,7 +41,7 @@ - + @@ -57,9 +57,25 @@ - + + + + + + + + + + + + + + + + + diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSharePanel.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSharePanel.java index 647a811320b8..18eb66b1292a 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSharePanel.java +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSharePanel.java @@ -14,17 +14,21 @@ public class GithubSharePanel { private JTextField myRepositoryTextField; private JCheckBox myPrivateCheckBox; private JTextArea myDescriptionTextArea; + private JTextField myRemoteTextField; private final GithubShareDialog myGithubShareDialog; public GithubSharePanel(final GithubShareDialog githubShareDialog) { myGithubShareDialog = githubShareDialog; - myRepositoryTextField.getDocument().addDocumentListener(new DocumentAdapter() { + myPrivateCheckBox.setSelected(false); + + DocumentAdapter changeListener = new DocumentAdapter() { @Override protected void textChanged(DocumentEvent e) { myGithubShareDialog.updateOkButton(); } - }); - myPrivateCheckBox.setSelected(false); + }; + myRepositoryTextField.getDocument().addDocumentListener(changeListener); + myRemoteTextField.getDocument().addDocumentListener(changeListener); } public JPanel getPanel() { @@ -43,6 +47,14 @@ public class GithubSharePanel { myRepositoryTextField.setText(name); } + public String getRemoteName() { + return myRemoteTextField.getText().trim(); + } + + public void setRemoteName(final String name) { + myRemoteTextField.setText(name); + } + public boolean isPrivate() { return myPrivateCheckBox.isSelected(); } diff --git a/plugins/github/src/org/jetbrains/plugins/github/util/GithubSettings.java b/plugins/github/src/org/jetbrains/plugins/github/util/GithubSettings.java index 7e98d47d8220..e86ffab49e4d 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/util/GithubSettings.java +++ b/plugins/github/src/org/jetbrains/plugins/github/util/GithubSettings.java @@ -62,6 +62,7 @@ public class GithubSettings implements PersistentStateComponent getLocation(@NotNull String protocolId, @NotNull String locationData, Project project) { if (!PROTOCOL_ID.equals(protocolId)) return Collections.emptyList(); + if (DumbService.isDumb(project)) return Collections.emptyList(); final String className = extractFullClassName(locationData); if (className == null) return Collections.emptyList(); diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java index 3bfc162ac74d..4a68f0933293 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java @@ -527,15 +527,15 @@ public class JavaFxPsiUtil { return false; } - public static PsiType getWrappedPropertyType(PsiField field, final Project project, final Map typeMap) { - final PsiType fieldType = field.getType(); - final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(fieldType); - final PsiClass fieldClass = resolveResult.getElement(); - if (fieldClass == null) return fieldType; - return CachedValuesManager.getManager(project).getCachedValue(field, new CachedValueProvider() { + public static PsiType getWrappedPropertyType(final PsiField field, final Project project, final Map typeMap) { + return CachedValuesManager.getCachedValue(field, new CachedValueProvider() { @Nullable @Override public Result compute() { + final PsiType fieldType = field.getType(); + final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(fieldType); + final PsiClass fieldClass = resolveResult.getElement(); + if (fieldClass == null) return Result.create(fieldType, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT); PsiType substitute = null; for (String typeName : typeMap.keySet()) { if (InheritanceUtil.isInheritor(fieldType, typeName)) { diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java index 1bab2d69e1c5..37f13312fc6c 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java +++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java @@ -28,6 +28,7 @@ import org.junit.runner.manipulation.Filter; import org.junit.runner.notification.RunNotifier; import org.junit.runners.BlockJUnit4ClassRunner; import org.junit.runners.Parameterized; +import org.junit.runners.Suite; import org.junit.runners.model.FrameworkMethod; import java.io.BufferedReader; @@ -324,13 +325,14 @@ public class JUnit4TestRunnerUtil { } } - private static class SelectedParameterizedRunner extends Parameterized { + private static class SelectedParameterizedRunner extends Suite { + public static final List NO_RUNNERS = new ArrayList(); private final String myName; private final String myMethodName; private Parameterized myRunnerClass; public SelectedParameterizedRunner(Class clazz, String name, String methodName, Class runnerClass) throws Throwable { - super(clazz); + super(clazz, NO_RUNNERS); myName = name; myMethodName = methodName; myRunnerClass = (Parameterized)runnerClass.getConstructor(new Class[] {Class.class}).newInstance(new Object[]{clazz}); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java index acae99f054f9..a10ef9750eea 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java @@ -341,6 +341,11 @@ public class MavenModuleImporter { level = LanguageLevel.parse(myMavenProject.getSourceLevel()); } + // default source and target settings of maven-compiler-plugin is 1.5, see details at http://maven.apache.org/plugins/maven-compiler-plugin + if (level == null) { + level = LanguageLevel.JDK_1_5; + } + myRootModelAdapter.setLanguageLevel(level); } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/configurers/MavenCompilerConfigurer.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/configurers/MavenCompilerConfigurer.java index 50f6f46baa23..e65e6f01d985 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/configurers/MavenCompilerConfigurer.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/configurers/MavenCompilerConfigurer.java @@ -36,11 +36,14 @@ public class MavenCompilerConfigurer extends MavenModuleConfigurer { if (module == null) return; String targetLevel = mavenProject.getTargetLevel(); - if (targetLevel != null) { - CompilerConfigurationImpl configuration = (CompilerConfigurationImpl)CompilerConfiguration.getInstance(project); - configuration.setBytecodeTargetLevel(module, targetLevel); + // default source and target settings of maven-compiler-plugin is 1.5, see details at http://maven.apache.org/plugins/maven-compiler-plugin + if (targetLevel == null) { + targetLevel = "1.5"; } + CompilerConfigurationImpl configuration = (CompilerConfigurationImpl)CompilerConfiguration.getInstance(project); + configuration.setBytecodeTargetLevel(module, targetLevel); + VirtualFile directoryFile = mavenProject.getDirectoryFile(); // Exclude src/main/archetype-resources diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java index 3e532757c54a..538a4bb005b6 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java +++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java @@ -123,10 +123,15 @@ public class SearchingForTestsTask extends Task.Backgroundable { @Override public void onSuccess() { - writeTempFile(); - finish(); + DumbService.getInstance(myProject).runWhenSmart(new Runnable() { + @Override + public void run() { + writeTempFile(); + finish(); - if (!Registry.is("testng_sm_runner")) myClient.startListening(myConfig); + if (!Registry.is("testng_sm_runner")) myClient.startListening(myConfig); + } + }); } @Override diff --git a/python/gen/com/jetbrains/commandInterface/gnuCommandLine/CommandLineElementTypes.java b/python/gen/com/jetbrains/commandInterface/gnuCommandLine/CommandLineElementTypes.java new file mode 100644 index 000000000000..d54609b4a048 --- /dev/null +++ b/python/gen/com/jetbrains/commandInterface/gnuCommandLine/CommandLineElementTypes.java @@ -0,0 +1,36 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.commandInterface.gnuCommandLine; + +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.PsiElement; +import com.intellij.lang.ASTNode; +import com.jetbrains.commandInterface.gnuCommandLine.psi.impl.*; + +public interface CommandLineElementTypes { + + IElementType ARGUMENT = new CommandLineElementType("ARGUMENT"); + IElementType COMMAND = new CommandLineElementType("COMMAND"); + IElementType OPTION = new CommandLineElementType("OPTION"); + + IElementType EQ = new IElementType("=", null); + IElementType LITERAL_STARTS_FROM_DIGIT = new IElementType("LITERAL_STARTS_FROM_DIGIT", null); + IElementType LITERAL_STARTS_FROM_LETTER = new IElementType("LITERAL_STARTS_FROM_LETTER", null); + IElementType LONG_OPTION_NAME_TOKEN = new IElementType("LONG_OPTION_NAME_TOKEN", null); + IElementType SHORT_OPTION_NAME_TOKEN = new IElementType("SHORT_OPTION_NAME_TOKEN", null); + + class Factory { + public static PsiElement createElement(ASTNode node) { + IElementType type = node.getElementType(); + if (type == ARGUMENT) { + return new CommandLineArgumentImpl(node); + } + else if (type == COMMAND) { + return new CommandLineCommandImpl(node); + } + else if (type == OPTION) { + return new CommandLineOptionImpl(node); + } + throw new AssertionError("Unknown element type: " + type); + } + } +} diff --git a/python/gen/com/jetbrains/commandInterface/gnuCommandLine/CommandLineParser.java b/python/gen/com/jetbrains/commandInterface/gnuCommandLine/CommandLineParser.java new file mode 100644 index 000000000000..157d84db3c92 --- /dev/null +++ b/python/gen/com/jetbrains/commandInterface/gnuCommandLine/CommandLineParser.java @@ -0,0 +1,167 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.commandInterface.gnuCommandLine; + +import com.intellij.lang.PsiBuilder; +import com.intellij.lang.PsiBuilder.Marker; +import static com.jetbrains.commandInterface.gnuCommandLine.CommandLineElementTypes.*; +import static com.jetbrains.commandInterface.gnuCommandLine.CommandLineParserUtil.*; +import com.intellij.psi.tree.IElementType; +import com.intellij.lang.ASTNode; +import com.intellij.psi.tree.TokenSet; +import com.intellij.lang.PsiParser; + +@SuppressWarnings({"SimplifiableIfStatement", "UnusedAssignment"}) +public class CommandLineParser implements PsiParser { + + public ASTNode parse(IElementType t, PsiBuilder b) { + parseLight(t, b); + return b.getTreeBuilt(); + } + + public void parseLight(IElementType t, PsiBuilder b) { + boolean r; + b = adapt_builder_(t, b, this, null); + Marker m = enter_section_(b, 0, _COLLAPSE_, null); + if (t == ARGUMENT) { + r = argument(b, 0); + } + else if (t == COMMAND) { + r = command(b, 0); + } + else if (t == OPTION) { + r = option(b, 0); + } + else { + r = parse_root_(t, b, 0); + } + exit_section_(b, 0, m, t, r, true, TRUE_CONDITION); + } + + protected boolean parse_root_(IElementType t, PsiBuilder b, int l) { + return root(b, l + 1); + } + + /* ********************************************************** */ + // LITERAL_STARTS_FROM_LETTER | LITERAL_STARTS_FROM_DIGIT + public static boolean argument(PsiBuilder b, int l) { + if (!recursion_guard_(b, l, "argument")) return false; + if (!nextTokenIs(b, "", LITERAL_STARTS_FROM_DIGIT, LITERAL_STARTS_FROM_LETTER)) return false; + boolean r; + Marker m = enter_section_(b, l, _NONE_, ""); + r = consumeToken(b, LITERAL_STARTS_FROM_LETTER); + if (!r) r = consumeToken(b, LITERAL_STARTS_FROM_DIGIT); + exit_section_(b, l, m, ARGUMENT, r, false, null); + return r; + } + + /* ********************************************************** */ + // LITERAL_STARTS_FROM_LETTER + public static boolean command(PsiBuilder b, int l) { + if (!recursion_guard_(b, l, "command")) return false; + if (!nextTokenIs(b, LITERAL_STARTS_FROM_LETTER)) return false; + boolean r; + Marker m = enter_section_(b); + r = consumeToken(b, LITERAL_STARTS_FROM_LETTER); + exit_section_(b, m, COMMAND, r); + return r; + } + + /* ********************************************************** */ + // LONG_OPTION_NAME_TOKEN + static boolean long_option_name(PsiBuilder b, int l) { + return consumeToken(b, LONG_OPTION_NAME_TOKEN); + } + + /* ********************************************************** */ + // short_option_name <> ? | long_option_name <> ? + public static boolean option(PsiBuilder b, int l) { + if (!recursion_guard_(b, l, "option")) return false; + if (!nextTokenIs(b, "