mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<Boolean> 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;
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -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;
|
||||
}
|
||||
|
||||
+13
-7
@@ -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<SmartTypePointer> 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<PsiType, SmartTypePointer>() {
|
||||
@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<LookupElement> set = new LinkedHashSet<LookupElement>();
|
||||
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()));
|
||||
}
|
||||
}
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
|
||||
class F {
|
||||
public void f() {}
|
||||
}
|
||||
|
||||
class E extends F {
|
||||
@Override
|
||||
<error descr="'f()' in 'E' clashes with 'f()' in 'F'; attempting to assign weaker access privileges ('protected'); was 'public'">protected</error> void f() {
|
||||
super.f();
|
||||
}
|
||||
}
|
||||
|
||||
class EE extends E {
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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> T[] getExtensions(@NotNull final ExtensionPointName<T> extensionPointName) {
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
+1
-2
@@ -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("<html><br>Master password is required to unlock the password database.<br>" +
|
||||
"The password database will be unlocked during this session<br>" +
|
||||
"for all subsystems.<br>" +
|
||||
|
||||
-57
@@ -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<String> 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);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+70
-4
@@ -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();
|
||||
|
||||
+10
-21
@@ -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<Object, String>() {
|
||||
@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<String> path = new ArrayDeque<String>();
|
||||
MyNode node = findNode(configurable);
|
||||
while (node != null) {
|
||||
path.push(node.myDisplayName);
|
||||
SimpleNode parent = node.getParent();
|
||||
|
||||
@@ -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<AWTEvent>() {
|
||||
@Override
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Void> myProcessor = new HttpRequests.RequestProcessor<Void>() {
|
||||
@@ -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 {
|
||||
|
||||
+2
-1
@@ -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<T extends BreakpointBase<?>> impleme
|
||||
@NotNull
|
||||
@Override
|
||||
public Promise<Void> flush(@NotNull Breakpoint breakpoint) {
|
||||
//noinspection unchecked
|
||||
return ((T)breakpoint).flush(this);
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
@@ -13,6 +13,8 @@
|
||||
<orderEntry type="module" module-name="protocol-reader" />
|
||||
<orderEntry type="library" name="Trove4j" level="project" />
|
||||
<orderEntry type="module" module-name="annotations" />
|
||||
<orderEntry type="module" module-name="util-rt" />
|
||||
<orderEntry type="module" module-name="platform-impl" />
|
||||
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
</module>
|
||||
-17
@@ -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<String, String>"), "writeMap");
|
||||
|
||||
abstract CharSequence getFullText();
|
||||
|
||||
abstract String getShortText(NamePath contextNamespace);
|
||||
|
||||
abstract String getWriteMethodName();
|
||||
}
|
||||
+20
@@ -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<String, String>"), "writeMap")
|
||||
}
|
||||
}
|
||||
-75
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+54
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
-48
@@ -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<TextOutConsumer> 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();
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package org.jetbrains.protocolReader
|
||||
|
||||
abstract class ClassScope(val generator: DomainGenerator, val classContextNamespace: NamePath) {
|
||||
private val additionalMemberTexts = ArrayList<TextOutConsumer>(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()
|
||||
}
|
||||
}
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
package org.jetbrains.protocolReader;
|
||||
|
||||
import org.jetbrains.jsonProtocol.ProtocolMetaModel;
|
||||
|
||||
abstract class CreateStandaloneTypeBindingVisitorBase implements TypeVisitor<StandaloneTypeBinding> {
|
||||
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();
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package org.jetbrains.protocolReader
|
||||
|
||||
abstract class CreateStandaloneTypeBindingVisitorBase(private val generator: DomainGenerator, protected val type: ProtocolMetaModel.StandaloneType) : TypeVisitor<StandaloneTypeBinding> {
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
-394
@@ -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<ProtocolMetaModel.Parameter> 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 <P extends ItemDescriptor.Named> void generateTopLevelOutputClass(@NotNull ClassNameScheme nameScheme,
|
||||
String baseName,
|
||||
String description,
|
||||
@Nullable TextOutConsumer baseType,
|
||||
@Nullable TextOutConsumer additionalMemberText,
|
||||
List<P> 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 <P extends ItemDescriptor.Named> void generateOutputClass(@NotNull TextOutput out,
|
||||
NamePath classNamePath,
|
||||
String description,
|
||||
@Nullable TextOutConsumer baseType,
|
||||
TextOutConsumer additionalMemberText,
|
||||
List<P> 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<ProtocolMetaModel.ObjectProperty> properties) {
|
||||
return createStandaloneObjectInputTypeBinding(getType(), properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StandaloneTypeBinding visitEnum(List<String> 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 <T extends ItemDescriptor> TypeDescriptor resolveType(T typedObject) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoxableType generateNestedObject(String description, List<ProtocolMetaModel.ObjectProperty> 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<ProtocolMetaModel.ObjectProperty> 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<String> 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<ProtocolMetaModel.ObjectProperty> 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<ProtocolMetaModel.Parameter> 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();
|
||||
}
|
||||
}
|
||||
+348
@@ -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<IOException>())
|
||||
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<BoxableType>(params!!.size()) else null
|
||||
if (hasParams) {
|
||||
classScope.writeMethodParameters<ProtocolMetaModel.Parameter>(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<ProtocolMetaModel.Parameter>(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<IOException>())
|
||||
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 <P : ItemDescriptor.Named> generateTopLevelOutputClass(nameScheme: ClassNameScheme, baseName: String, description: String?, baseType: TextOutConsumer?, additionalMemberText: TextOutConsumer?, properties: List<P>?) {
|
||||
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 <P : ItemDescriptor.Named> generateOutputClass(out: TextOutput, classNamePath: NamePath, description: String?, baseType: TextOutConsumer?, additionalMemberText: TextOutConsumer?, properties: List<P>?) {
|
||||
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<P>(out, properties)
|
||||
classScope.writeAdditionalMembers(out)
|
||||
out.closeBlock()
|
||||
}
|
||||
|
||||
fun createStandaloneOutputTypeBinding(type: ProtocolMetaModel.StandaloneType, name: String): StandaloneTypeBinding {
|
||||
return Generator.switchByType<StandaloneTypeBinding>(type, MyCreateStandaloneTypeBindingVisitorBase(this, type, name))
|
||||
}
|
||||
|
||||
fun createStandaloneInputTypeBinding(type: ProtocolMetaModel.StandaloneType): StandaloneTypeBinding {
|
||||
return Generator.switchByType<StandaloneTypeBinding>(type, object : CreateStandaloneTypeBindingVisitorBase(this, type) {
|
||||
override fun visitObject(properties: List<ProtocolMetaModel.ObjectProperty>?): StandaloneTypeBinding {
|
||||
return createStandaloneObjectInputTypeBinding(type, properties)
|
||||
}
|
||||
|
||||
override fun visitEnum(enumConstants: List<String>): 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 <T : ItemDescriptor> resolveType(typedObject: T): TypeDescriptor {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun generateNestedObject(description: String?, properties: List<ProtocolMetaModel.ObjectProperty>?) = 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<ProtocolMetaModel.ObjectProperty>?): 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<IOException>())
|
||||
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<String>, 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<IOException>())
|
||||
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<ProtocolMetaModel.ObjectProperty>?): 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<IOException>())
|
||||
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<ProtocolMetaModel.Parameter>?, 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
|
||||
}
|
||||
}
|
||||
}
|
||||
-66
@@ -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<Path> unusedFiles;
|
||||
|
||||
FileSet(Path rootDir) throws IOException {
|
||||
this.rootDir = rootDir;
|
||||
unusedFiles = new THashSet<Path>();
|
||||
Files.walkFileTree(rootDir, new SimpleFileVisitor<Path>() {
|
||||
@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<Path>() {
|
||||
@Override
|
||||
public boolean execute(Path path) {
|
||||
try {
|
||||
if (Files.deleteIfExists(path)) {
|
||||
Path parent = path.getParent();
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(parent)) {
|
||||
if (!stream.iterator().hasNext()) {
|
||||
Files.delete(parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+56
@@ -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<IOException>())]
|
||||
(private val rootDir: Path) {
|
||||
SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
|
||||
private val unusedFiles: THashSet<Path>
|
||||
|
||||
{
|
||||
unusedFiles = THashSet<Path>()
|
||||
Files.walkFileTree(rootDir, object : SimpleFileVisitor<Path>() {
|
||||
throws(javaClass<IOException>())
|
||||
override fun preVisitDirectory(dir: Path, attrs: BasicFileAttributes): FileVisitResult {
|
||||
return if (Files.isHidden(dir)) FileVisitResult.SKIP_SUBTREE else FileVisitResult.CONTINUE
|
||||
}
|
||||
|
||||
throws(javaClass<IOException>())
|
||||
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<Path> {
|
||||
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
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
-314
@@ -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<String> jsonProtocolParserClassNames = new ArrayList<>();
|
||||
final List<ParserRootInterfaceItem> 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<Domain> domainList = metamodel.domains();
|
||||
Map<String, DomainGenerator> 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<TypeDescriptor>() {
|
||||
@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<String> 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<ObjectProperty> 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<ParserRootInterfaceItem> 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> R switchByType(@NotNull ItemDescriptor typedObject, @NotNull TypeVisitor<R> 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<ObjectProperty> 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<String> BAD_METHOD_NAMES = new HashSet<>(Collections.singletonList("this"));
|
||||
}
|
||||
+288
@@ -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<IOException>())]
|
||||
(outputDir: String, rootPackage: String, requestClassName: String) {
|
||||
|
||||
val jsonProtocolParserClassNames = ArrayList<String>()
|
||||
val parserRootInterfaceItems = ArrayList<ParserRootInterfaceItem>()
|
||||
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<IOException>())
|
||||
fun go(metamodel: Root) {
|
||||
initializeKnownTypes()
|
||||
|
||||
val domainList = metamodel.domains()
|
||||
val domainGeneratorMap = HashMap<String, DomainGenerator>()
|
||||
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<TypeDescriptor> {
|
||||
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<String>): 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<ArrayItemType>(items).type
|
||||
return TypeDescriptor(ListType(type), optional, false, type == BoxableType.ANY_STRING)
|
||||
}
|
||||
|
||||
override fun visitObject(properties: List<ObjectProperty>?): TypeDescriptor {
|
||||
return TypeDescriptor(scope.generateNestedObject(typedObject.description(), properties!!), optional)
|
||||
}
|
||||
|
||||
override fun visitUnknown(): TypeDescriptor {
|
||||
return TypeDescriptor(BoxableType.STRING, optional, false, true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
throws(javaClass<IOException>())
|
||||
private fun generateParserInterfaceList() {
|
||||
val fileUpdater = startJavaFile(naming.inputPackage, PARSER_INTERFACE_LIST_CLASS_NAME + ".java")
|
||||
// Write classes in stable order.
|
||||
Collections.sort<String>(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<IOException>())
|
||||
private fun generateParserRoot(parserRootInterfaceItems: List<ParserRootInterfaceItem>) {
|
||||
val fileUpdater = startJavaFile(naming.inputPackage, READER_INTERFACE_NAME + ".java")
|
||||
// Write classes in stable order.
|
||||
Collections.sort<ParserRootInterfaceItem>(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<IOException>())
|
||||
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 <R> switchByType(typedObject: ItemDescriptor, visitor: TypeVisitor<R>): 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"))
|
||||
}
|
||||
}
|
||||
-86
@@ -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<? extends Named> 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<String> 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<ObjectProperty> 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
package org.jetbrains.protocolReader
|
||||
|
||||
class InputClassScope(generator: DomainGenerator, namePath: NamePath) : ClassScope(generator, namePath) {
|
||||
|
||||
fun generateDeclarationBody(out: TextOutput, list: List<Named>) {
|
||||
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>(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<String>): 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<ObjectProperty>?): 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<ObjectProperty>(property)
|
||||
propertyTypeData.writeAnnotations(out)
|
||||
|
||||
out.append(propertyTypeData.type.getShortText(classContextNamespace) + ' ' + methodName + "();").newLine()
|
||||
}
|
||||
}
|
||||
out.closeBlock()
|
||||
}
|
||||
})
|
||||
return StandaloneType(NamePath(objectName, classContextNamespace), "writeMessage")
|
||||
}
|
||||
}
|
||||
}
|
||||
-44
@@ -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) + '>';
|
||||
}
|
||||
}
|
||||
+34
@@ -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) + '>'
|
||||
}
|
||||
}
|
||||
-42
@@ -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 <T extends ItemDescriptor> TypeDescriptor resolveType(T typedObject) {
|
||||
return classScope.generator.generator.resolveType(typedObject, this);
|
||||
}
|
||||
|
||||
protected String getMemberName() {
|
||||
return memberName;
|
||||
}
|
||||
|
||||
public abstract BoxableType generateEnum(String description, List<String> enumConstants);
|
||||
public abstract BoxableType generateNestedObject(String description, List<ProtocolMetaModel.ObjectProperty> propertyList);
|
||||
|
||||
@Override
|
||||
public String getDomainName() {
|
||||
return classScope.generator.domain.domain();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeData.Direction getTypeDirection() {
|
||||
return classScope.getTypeDirection();
|
||||
}
|
||||
}
|
||||
+17
@@ -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 <T : ItemDescriptor> resolveType(typedObject: T): TypeDescriptor {
|
||||
return classScope.generator.generator.resolveType(typedObject, this)
|
||||
}
|
||||
|
||||
public abstract fun generateEnum(description: String?, enumConstants: List<String>): BoxableType
|
||||
|
||||
override fun getDomainName() = classScope.generator.domain.domain()
|
||||
|
||||
override fun getTypeDirection() = classScope.getTypeDirection()
|
||||
}
|
||||
-75
@@ -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<ProtocolMetaModel.ObjectProperty> 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<String> 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 <T extends ItemDescriptor> TypeDescriptor resolveType(T typedObject) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoxableType generateNestedObject(String description, List<ProtocolMetaModel.ObjectProperty> properties) {
|
||||
return context.generateNestedObject("Item", description, properties);
|
||||
}
|
||||
}).getType());
|
||||
}
|
||||
}, generator.generator.naming.outputTypedef, TypeData.Direction.OUTPUT);
|
||||
}
|
||||
}
|
||||
+44
@@ -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<ProtocolMetaModel.ObjectProperty>?): 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<String>): 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 <T : ItemDescriptor> resolveType(typedObject: T) = throw UnsupportedOperationException()
|
||||
|
||||
override fun generateNestedObject(description: String?, properties: List<ProtocolMetaModel.ObjectProperty>?): BoxableType {
|
||||
return context.generateNestedObject("Item", description, properties)
|
||||
}
|
||||
}).type)
|
||||
}
|
||||
}, generator.generator.naming.outputTypedef, TypeData.Direction.OUTPUT)
|
||||
}
|
||||
}
|
||||
-45
@@ -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);
|
||||
}
|
||||
}
|
||||
+30
@@ -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)
|
||||
}
|
||||
}
|
||||
-245
@@ -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);
|
||||
}
|
||||
|
||||
<P extends ItemDescriptor.Named> void generate(@NotNull TextOutput out, @Nullable List<P> parameters) {
|
||||
if (parameters == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<P> mandatoryParameters = new ArrayList<>();
|
||||
List<P> 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 <P extends ItemDescriptor.Named> void generateConstructor(@NotNull TextOutput out, @NotNull List<P> 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();
|
||||
}
|
||||
|
||||
<P extends ItemDescriptor.Named> void writeWriteCalls(@NotNull TextOutput out, @NotNull List<P> 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]);
|
||||
}
|
||||
}
|
||||
|
||||
<P extends ItemDescriptor.Named> void writeMethodParameters(@NotNull TextOutput out, @NotNull List<P> 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<String> enumConstants) {
|
||||
return new StandaloneType(new NamePath(Generator.capitalizeFirstChar(getMemberName()), getClassContextNamespace()), "writeEnum");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoxableType generateNestedObject(String description, List<ProtocolMetaModel.ObjectProperty> propertyList) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
private static void appendEnumClass(TextOutput out, String description, List<String> 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();
|
||||
}
|
||||
}
|
||||
+225
@@ -0,0 +1,225 @@
|
||||
package org.jetbrains.protocolReader
|
||||
|
||||
class OutputClassScope(generator: DomainGenerator, classNamePath: NamePath) : ClassScope(generator, classNamePath) {
|
||||
fun <P : ItemDescriptor.Named> generate(out: TextOutput, parameters: List<P>?) {
|
||||
if (parameters == null) {
|
||||
return
|
||||
}
|
||||
|
||||
val mandatoryParameters = ArrayList<P>()
|
||||
val optionalParameters = ArrayList<P>()
|
||||
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<P>(parameter)
|
||||
if (typeData.type.getFullText() == "int[]") {
|
||||
val types = arrayOfNulls<BoxableType>(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<P>(parameter).type.getShortText(classContextNamespace)
|
||||
if (type == javaClass<JsonReaderEx>().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 <P : ItemDescriptor.Named> generateConstructor(out: TextOutput, parameters: List<P>, parameterTypes: Array<BoxableType?> = arrayOfNulls<BoxableType>(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 <P : ItemDescriptor.Named> writeWriteCalls(out: TextOutput, parameters: List<P>, parameterTypes: Array<BoxableType?>, 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 <P : ItemDescriptor.Named> writeMethodParameters(out: TextOutput, parameters: List<P>, parameterTypes: Array<BoxableType?>) {
|
||||
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<P>(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<ItemDescriptor.Named>(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<String>): BoxableType {
|
||||
return StandaloneType(NamePath(Generator.capitalizeFirstChar(memberName), classContextNamespace), "writeEnum")
|
||||
}
|
||||
|
||||
override fun generateNestedObject(description: String?, properties: List<ProtocolMetaModel.ObjectProperty>?) = throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
private fun appendEnumClass(out: TextOutput, description: String?, enumConstants: List<String>, 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()
|
||||
}
|
||||
}
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
package org.jetbrains.protocolReader;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
class ParserRootInterfaceItem implements Comparable<ParserRootInterfaceItem> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
+26
@@ -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<ParserRootInterfaceItem> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
-45
@@ -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();
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package org.jetbrains.protocolReader
|
||||
|
||||
import org.jetbrains.protocolReader.ProtocolModelGenerator
|
||||
|
||||
public class ProtocolModelGenerator {
|
||||
default object {
|
||||
throws(javaClass<IOException>())
|
||||
public fun main(args: Array<String>) {
|
||||
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<IOException>())
|
||||
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<String>) = ProtocolModelGenerator.main(args)
|
||||
-16
@@ -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();
|
||||
|
||||
<T extends ItemDescriptor> TypeDescriptor resolveType(T typedObject);
|
||||
|
||||
BoxableType generateNestedObject(String description,
|
||||
List<ProtocolMetaModel.ObjectProperty> properties);
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package org.jetbrains.protocolReader
|
||||
|
||||
trait ResolveAndGenerateScope {
|
||||
public fun getDomainName(): String
|
||||
public fun getTypeDirection(): TypeData.Direction
|
||||
|
||||
public fun <T : ItemDescriptor> resolveType(typedObject: T): TypeDescriptor
|
||||
|
||||
public fun generateNestedObject(description: String?, properties: List<ProtocolMetaModel.ObjectProperty>?): BoxableType
|
||||
}
|
||||
-62
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+53
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
-45
@@ -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<ProtocolMetaModel.ObjectProperty> 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);
|
||||
}
|
||||
}
|
||||
+35
@@ -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<ProtocolMetaModel.ObjectProperty>?): 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
package org.jetbrains.protocolReader;
|
||||
|
||||
public interface TextOutConsumer {
|
||||
void append(TextOutput out);
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package org.jetbrains.protocolReader
|
||||
|
||||
public trait TextOutConsumer {
|
||||
public fun append(out: TextOutput)
|
||||
}
|
||||
-176
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+159
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-50
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
-61
@@ -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<Pair<String, String>, TypeData> map = new THashMap<>();
|
||||
private Map<String, DomainGenerator> domainGeneratorMap;
|
||||
private final List<StandaloneTypeBinding> typesToGenerate = new ArrayList<>();
|
||||
|
||||
void setDomainGeneratorMap(Map<String, DomainGenerator> 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<String, String> key = Pair.create(domainName, typeName);
|
||||
TypeData result = map.get(key);
|
||||
if (result == null) {
|
||||
result = new TypeData(typeName);
|
||||
map.put(key, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+50
@@ -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<Pair<String, String>, TypeData>()
|
||||
private var domainGeneratorMap: Map<String, DomainGenerator>? = null
|
||||
private val typesToGenerate = ArrayList<StandaloneTypeBinding>()
|
||||
|
||||
fun setDomainGeneratorMap(domainGeneratorMap: Map<String, DomainGenerator>) {
|
||||
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<IOException>())
|
||||
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<String, String>(domainName, typeName)
|
||||
var result: TypeData? = map.get(key)
|
||||
if (result == null) {
|
||||
result = TypeData(typeName)
|
||||
map.put(key, result)
|
||||
}
|
||||
return result!!
|
||||
}
|
||||
}
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
package org.jetbrains.protocolReader;
|
||||
|
||||
import org.jetbrains.jsonProtocol.ProtocolMetaModel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
interface TypeVisitor<R> {
|
||||
R visitRef(String refName);
|
||||
|
||||
R visitBoolean();
|
||||
|
||||
R visitEnum(List<String> enumConstants);
|
||||
|
||||
R visitString();
|
||||
|
||||
R visitInteger();
|
||||
|
||||
R visitNumber();
|
||||
|
||||
R visitArray(ProtocolMetaModel.ArrayItemType items);
|
||||
|
||||
R visitObject(List<ProtocolMetaModel.ObjectProperty> properties);
|
||||
|
||||
R visitMap();
|
||||
|
||||
R visitUnknown();
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package org.jetbrains.protocolReader
|
||||
|
||||
trait TypeVisitor<R> {
|
||||
public fun visitRef(refName: String): R
|
||||
|
||||
public fun visitBoolean(): R
|
||||
|
||||
public fun visitEnum(enumConstants: List<String>): 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<ProtocolMetaModel.ObjectProperty>?): R
|
||||
|
||||
public fun visitMap(): R
|
||||
|
||||
public fun visitUnknown(): R
|
||||
}
|
||||
-1
@@ -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;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="true">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
|
||||
@@ -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<FieldLoader>()
|
||||
@@ -15,10 +16,10 @@ class FieldProcessor(private val reader: InterfaceReader, typeClass: Class<*>) {
|
||||
val volatileFields = ArrayList<VolatileFieldBinding>()
|
||||
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<String>()
|
||||
for (method in methods) {
|
||||
|
||||
@@ -40,7 +40,7 @@ private class State(typeWriters: Collection<TypeWriter<*>>, private val basePack
|
||||
private val typesWithFactories = THashSet<TypeWriter<*>>()
|
||||
val typesWithFactoriesList = ArrayList<TypeWriter<*>>();
|
||||
|
||||
{
|
||||
init {
|
||||
var uniqueCode = 0
|
||||
val result = THashMap<TypeWriter<*>, String>(typeWriters.size())
|
||||
for (handler in typeWriters) {
|
||||
|
||||
@@ -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<Class<*>>): InterfaceReader {
|
||||
val __ = InterfaceReader(LinkedHashMap<Class<*>, TypeWriter<*>>(protocolInterfaces.size()))
|
||||
@@ -130,6 +131,9 @@ class InterfaceReader(val typeToTypeHandler: LinkedHashMap<Class<*>, TypeWriter<
|
||||
if (jsonField != null && jsonField.allowAnyPrimitiveValue()) {
|
||||
return RAW_STRING_PARSER
|
||||
}
|
||||
else if ((jsonField != null && jsonField.optional()) || method.getAnnotation<JsonOptionalField>(javaClass<JsonOptionalField>()) != null) {
|
||||
return NULLABLE_STRING_PARSER
|
||||
}
|
||||
}
|
||||
return STRING_PARSER
|
||||
}
|
||||
@@ -220,6 +224,7 @@ class InterfaceReader(val typeToTypeHandler: LinkedHashMap<Class<*>, 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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<ROOT>(val packageName: String, val className: String, readerRootClass: Class<ROOT>, protocolInterfaces: Array<Class<*>>, basePackagesMap: Map<Class<*>, String>? = null) {
|
||||
val basePackagesMap: Collection<Map<Class<*>, String>>
|
||||
|
||||
|
||||
+4
-3
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
@@ -9,6 +9,7 @@
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="gson" level="project" />
|
||||
<orderEntry type="module" module-name="protocol-reader" />
|
||||
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
|
||||
<orderEntry type="module" module-name="platform-impl" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
</module>
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
package org.jetbrains.jsonProtocol;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ItemDescriptor {
|
||||
String description();
|
||||
|
||||
String type();
|
||||
|
||||
List<String> 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<ProtocolMetaModel.ObjectProperty> properties();
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package org.jetbrains.jsonProtocol
|
||||
|
||||
public trait ItemDescriptor {
|
||||
public fun description(): String?
|
||||
|
||||
public fun type(): String
|
||||
|
||||
public fun getEnum(): List<String>?
|
||||
|
||||
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<ProtocolMetaModel.ObjectProperty>?
|
||||
}
|
||||
}
|
||||
-223
@@ -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<Domain> domains();
|
||||
}
|
||||
|
||||
@JsonType
|
||||
interface Version {
|
||||
String major();
|
||||
String minor();
|
||||
}
|
||||
|
||||
@JsonType
|
||||
interface Domain {
|
||||
String domain();
|
||||
|
||||
@JsonOptionalField
|
||||
List<StandaloneType> types();
|
||||
|
||||
List<Command> commands();
|
||||
|
||||
@JsonOptionalField
|
||||
List<Event> events();
|
||||
|
||||
@JsonOptionalField
|
||||
String description();
|
||||
|
||||
@JsonOptionalField
|
||||
boolean hidden();
|
||||
}
|
||||
|
||||
@JsonType
|
||||
interface Command {
|
||||
String name();
|
||||
|
||||
@JsonOptionalField
|
||||
List<Parameter> parameters();
|
||||
|
||||
@JsonOptionalField
|
||||
List<Parameter> 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<String> 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<Parameter> 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<ObjectProperty> properties();
|
||||
|
||||
@Override
|
||||
@JsonField(jsonLiteralName = "enum")
|
||||
@JsonOptionalField
|
||||
List<String> 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<String> getEnum();
|
||||
|
||||
@Override
|
||||
@JsonOptionalField
|
||||
List<ObjectProperty> 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<String> 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";
|
||||
}
|
||||
+196
@@ -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<Domain>
|
||||
}
|
||||
|
||||
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<StandaloneType>?
|
||||
|
||||
public fun commands(): List<Command>
|
||||
|
||||
JsonOptionalField
|
||||
public fun events(): List<Event>?
|
||||
|
||||
JsonOptionalField
|
||||
public fun description(): String
|
||||
|
||||
JsonOptionalField
|
||||
public fun hidden(): Boolean
|
||||
}
|
||||
|
||||
JsonType
|
||||
public trait Command {
|
||||
public fun name(): String
|
||||
|
||||
JsonOptionalField
|
||||
public fun parameters(): List<Parameter>?
|
||||
|
||||
JsonOptionalField
|
||||
public fun returns(): List<Parameter>?
|
||||
|
||||
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<String>
|
||||
|
||||
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<Parameter>
|
||||
|
||||
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<ObjectProperty>
|
||||
|
||||
JsonField(name = "enum")
|
||||
JsonOptionalField
|
||||
override fun getEnum(): List<String>
|
||||
|
||||
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<String>
|
||||
|
||||
JsonOptionalField
|
||||
override fun properties(): List<ObjectProperty>
|
||||
}
|
||||
|
||||
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<String>
|
||||
|
||||
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"
|
||||
}
|
||||
}
|
||||
-15
@@ -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;
|
||||
}
|
||||
+12
@@ -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<IOException>())
|
||||
public fun parseRoot(reader: JsonReaderEx): Root
|
||||
}
|
||||
-11
@@ -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()));
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package org.jetbrains.jsonProtocol
|
||||
|
||||
import org.jetbrains.protocolReader.ReaderGenerator
|
||||
|
||||
fun main(args: Array<String>) = ReaderGenerator.generate(args, ReaderGenerator.GenerateConfiguration("org.jetbrains.jsonProtocol", "ProtocolSchemaReaderImpl", javaClass<ProtocolSchemaReader>(), javaClass<ProtocolMetaModel>().getDeclaredClasses()))
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<String> 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<GitRemote, String>() {
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -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;
|
||||
|
||||
@@ -139,7 +139,7 @@ public class GithubRepositoryEditor extends BaseRepositoryEditor<GithubRepositor
|
||||
);
|
||||
}
|
||||
catch (IOException e) {
|
||||
GithubNotifications.showErrorDialog(myProject, "Can't get access token", e);
|
||||
GithubNotifications.showErrorDialog(myProject, "Can't Get Access Token", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.github.ui.GithubSettingsPanel">
|
||||
<grid id="27dc6" binding="myPane" layout-manager="GridLayoutManager" row-count="6" column-count="5" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="27dc6" binding="myPane" layout-manager="GridLayoutManager" row-count="7" column-count="5" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="646" height="400"/>
|
||||
@@ -28,7 +28,7 @@
|
||||
</component>
|
||||
<vspacer id="6ace">
|
||||
<constraints>
|
||||
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
<grid row="6" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<component id="45bab" class="com.intellij.ui.components.JBLabel">
|
||||
@@ -167,7 +167,7 @@
|
||||
<grid id="d384a" layout-manager="GridLayoutManager" row-count="1" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="4" column="0" row-span="1" col-span="5" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<grid row="5" column="0" row-span="1" col-span="5" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<clientProperties>
|
||||
@@ -204,7 +204,15 @@
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<vspacer id="2a9d8">
|
||||
<component id="e2613" class="com.intellij.ui.components.JBCheckBox" binding="myCloneUsingSshCheckBox" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="4" column="0" row-span="1" col-span="5" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Clone git repositories using ssh"/>
|
||||
</properties>
|
||||
</component>
|
||||
<vspacer id="5f470">
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="1" col-span="5" vsize-policy="0" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false">
|
||||
<minimum-size width="-1" height="15"/>
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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<String> myAvailableNames;
|
||||
private final Set<String> myAvailableRemotes;
|
||||
|
||||
public GithubShareDialog(final Project project, final Set<String> availableNames, final boolean privateRepoAllowed) {
|
||||
public GithubShareDialog(Project project, Set<String> availableNames, Set<String> 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);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.github.ui.GithubSharePanel">
|
||||
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="3" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="4" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="376" height="98"/>
|
||||
<xy x="20" y="20" width="383" height="98"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
@@ -26,7 +26,7 @@
|
||||
</component>
|
||||
<scrollpane id="83208" class="com.intellij.ui.components.JBScrollPane">
|
||||
<constraints>
|
||||
<grid row="1" column="1" row-span="1" col-span="2" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false">
|
||||
<grid row="2" column="1" row-span="1" col-span="2" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="250" height="100"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
@@ -41,7 +41,7 @@
|
||||
</scrollpane>
|
||||
<component id="d1ca7" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="9" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="9" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Description"/>
|
||||
@@ -57,9 +57,25 @@
|
||||
</component>
|
||||
<vspacer id="18a1f">
|
||||
<constraints>
|
||||
<grid row="2" column="2" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
<grid row="3" column="2" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<component id="539e4" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Remote name:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="7cb3e" class="javax.swing.JTextField" binding="myRemoteTextField">
|
||||
<constraints>
|
||||
<grid row="1" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="150" height="-1"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ public class GithubSettings implements PersistentStateComponent<GithubSettings.S
|
||||
public int CONNECTION_TIMEOUT = 5000;
|
||||
public boolean VALID_GIT_AUTH = true;
|
||||
public ThreeState CREATE_PULL_REQUEST_CREATE_REMOTE = ThreeState.UNSURE;
|
||||
public boolean CLONE_GIT_USING_SSH = false;
|
||||
}
|
||||
|
||||
public static GithubSettings getInstance() {
|
||||
@@ -132,6 +133,10 @@ public class GithubSettings implements PersistentStateComponent<GithubSettings.S
|
||||
return passwordSafe.getSettings().getProviderType() == PasswordSafeSettings.ProviderType.MASTER_PASSWORD;
|
||||
}
|
||||
|
||||
public boolean isCloneGitUsingSsh() {
|
||||
return myState.CLONE_GIT_USING_SSH;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ThreeState getCreatePullRequestCreateRemote() {
|
||||
return myState.CREATE_PULL_REQUEST_CREATE_REMOTE;
|
||||
@@ -161,6 +166,10 @@ public class GithubSettings implements PersistentStateComponent<GithubSettings.S
|
||||
myState.OPEN_IN_BROWSER_GIST = openInBrowserGist;
|
||||
}
|
||||
|
||||
public void setCloneGitUsingSsh(boolean value) {
|
||||
myState.CLONE_GIT_USING_SSH = value;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String getPassword() {
|
||||
String password;
|
||||
|
||||
@@ -209,6 +209,11 @@ public class GithubUrlUtil {
|
||||
|
||||
@NotNull
|
||||
public static String getCloneUrl(@NotNull String user, @NotNull String repo) {
|
||||
return getGithubHost() + "/" + user + "/" + repo + ".git";
|
||||
if (GithubSettings.getInstance().isCloneGitUsingSsh()) {
|
||||
return "git@" + getGitHostWithoutProtocol() + ":" + user + "/" + repo + ".git";
|
||||
}
|
||||
else {
|
||||
return "https://" + getGitHostWithoutProtocol() + "/" + user + "/" + repo + ".git";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -17,13 +17,13 @@ package org.jetbrains.plugins.gradle.execution.test.runner;
|
||||
|
||||
import com.intellij.execution.Location;
|
||||
import com.intellij.execution.PsiLocation;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.testIntegration.TestLocationProvider;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -43,6 +43,7 @@ public class GradleUrlProvider implements TestLocationProvider {
|
||||
@NotNull
|
||||
public List<Location> 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();
|
||||
|
||||
@@ -527,15 +527,15 @@ public class JavaFxPsiUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static PsiType getWrappedPropertyType(PsiField field, final Project project, final Map<String, PsiType> 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<PsiType>() {
|
||||
public static PsiType getWrappedPropertyType(final PsiField field, final Project project, final Map<String, PsiType> typeMap) {
|
||||
return CachedValuesManager.getCachedValue(field, new CachedValueProvider<PsiType>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public Result<PsiType> 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)) {
|
||||
|
||||
@@ -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});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user