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:
@@ -145,7 +145,7 @@ def layoutFull(String home, String targetDirectory, String patchedDescriptorDir
|
||||
}
|
||||
|
||||
jar("bootstrap.jar") { module("bootstrap") }
|
||||
|
||||
|
||||
jar("jps-launcher.jar") { module("jps-launcher") }
|
||||
|
||||
jar("resources.jar") {
|
||||
@@ -557,7 +557,14 @@ public def layoutCommunityPlugins(String home) {
|
||||
}
|
||||
}
|
||||
|
||||
layoutPlugin("java-decompiler")
|
||||
pluginDir("java-decompiler") {
|
||||
dir("lib") {
|
||||
jar("java-decompiler.jar") {
|
||||
module("java-decompiler-engine")
|
||||
module("java-decompiler-plugin")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ libraryLicense(name: "JavaCVS", attachedTo: "javacvs-src", version: "no version
|
||||
libraryLicense(name: "JAXB", libraryName: "JAXB", version: "2.2.4-1", license: "CDDL 1.1", url: "http://jaxb.java.net/", licenseUrl: "http://glassfish.java.net/public/CDDL+GPL_1_1.html")
|
||||
libraryLicense(name: "Jaxen", version: "", license: "modified Apache", url: "http://www.jaxen.org/", licenseUrl: "http://www.jaxen.org/license.html")
|
||||
libraryLicense(name: "JavaHelp", version: "2.0_02", license: "included as license/javahelp_license.html in IntelliJ IDEA distribution", url: "http://java.sun.com/products/javahelp/")
|
||||
libraryLicense(name: "Java-WebSocket", version: "1.3.0", license: "MIT", url: "https://github.com/TooTallNate/Java-WebSocket", licenseUrl:"https://github.com/TooTallNate/Java-WebSocket/blob/master/LICENSE")
|
||||
libraryLicense(name: "Java-WebSocket", libraryName: "java_websocket.jar", version: "1.3.0", license: "MIT", url: "https://github.com/TooTallNate/Java-WebSocket", licenseUrl:"https://github.com/TooTallNate/Java-WebSocket/blob/master/LICENSE")
|
||||
libraryLicense(name: "JCIP Annotations", libraryName: "jcip", license: "Creative Commons Attribution License", url: "http://www.jcip.net", licenseUrl: "http://creativecommons.org/licenses/by/2.5")
|
||||
libraryLicense(name: "JDOM", version: "1.1 (with patches by JetBrains)", license: "modified Apache", url: "http://www.jdom.org/", licenseUrl: "http://www.jdom.org/docs/faq.html#a0030")
|
||||
libraryLicense(name: "javawriter", libraryName: "javawriter", license: "Apache 2.0", url: "https://github.com/square/javawriter")
|
||||
|
||||
@@ -138,9 +138,13 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
|
||||
presentation = new TypedStringValuePresentation(value, type);
|
||||
}
|
||||
else {
|
||||
@SuppressWarnings("ThrowableResultOfMethodCallIgnored")
|
||||
EvaluateException exception = myValueDescriptor.getEvaluateException();
|
||||
if (myValueDescriptor.getLastRenderer() instanceof ToStringRenderer && exception == null) {
|
||||
presentation = new XRegularValuePresentation(StringUtil.wrapWithDoubleQuote(value.substring(0,Math.min(value.length(), XValueNode.MAX_VALUE_LENGTH))), type);
|
||||
presentation = new XRegularValuePresentation(StringUtil.wrapWithDoubleQuote(truncateToMaxLength(value)), type);
|
||||
}
|
||||
else if (myValueDescriptor.getLastRenderer() instanceof CompoundReferenceRenderer && exception == null) {
|
||||
presentation = new XRegularValuePresentation(truncateToMaxLength(value), type);
|
||||
}
|
||||
else {
|
||||
presentation = new JavaValuePresentation(value, type, exception != null ? exception.getMessage() : null);
|
||||
@@ -180,6 +184,10 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
|
||||
});
|
||||
}
|
||||
|
||||
private static String truncateToMaxLength(String value) {
|
||||
return value.substring(0, Math.min(value.length(), XValueNode.MAX_VALUE_LENGTH));
|
||||
}
|
||||
|
||||
private static class JavaValuePresentation extends XValuePresentation implements XValueCompactPresentation {
|
||||
private final String myValue;
|
||||
private final String myType;
|
||||
|
||||
@@ -83,7 +83,7 @@ public class LabelRenderer extends com.intellij.debugger.ui.tree.render.Referenc
|
||||
}
|
||||
EvaluationContext thisEvaluationContext = evaluationContext.createEvaluationContext(value);
|
||||
Value labelValue = evaluator.evaluate(thisEvaluationContext);
|
||||
result = DebuggerUtils.convertToPresentationString(DebuggerUtils.getValueAsString(thisEvaluationContext, labelValue));
|
||||
result = DebuggerUtils.getValueAsString(thisEvaluationContext, labelValue);
|
||||
}
|
||||
catch (final EvaluateException ex) {
|
||||
throw new EvaluateException(DebuggerBundle.message("error.unable.to.evaluate.expression") + " " + ex.getMessage(), ex);
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.intellij.debugger.ui.tree.ValueDescriptor;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.JDOMExternalizerUtil;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.CommonClassNames;
|
||||
import com.intellij.psi.PsiExpression;
|
||||
import com.intellij.ui.classFilter.ClassFilter;
|
||||
@@ -78,8 +79,7 @@ public class ToStringRenderer extends NodeRendererImpl {
|
||||
BatchEvaluator.getBatchEvaluator(evaluationContext.getDebugProcess()).invoke(new ToStringCommand(evaluationContext, value) {
|
||||
public void evaluationResult(String message) {
|
||||
valueDescriptor.setValueLabel(
|
||||
// no need to add quotes and escape characters here, XValueTextRendererImpl handles the presentation
|
||||
message == null? "" : /*"\"" + DebuggerUtils.convertToPresentationString(*/DebuggerUtilsEx.truncateString(message)/*) + "\""*/
|
||||
StringUtil.notNullize(message)
|
||||
);
|
||||
labelListener.labelChanged();
|
||||
}
|
||||
|
||||
+6
-2
@@ -84,10 +84,14 @@ class ContractInferenceInterpreter {
|
||||
}
|
||||
|
||||
List<MethodContract> inferContracts() {
|
||||
final boolean notNull = NullableNotNullManager.isNotNull(myMethod);
|
||||
List<MethodContract> contracts = doInferContracts();
|
||||
if (contracts.isEmpty()) return contracts;
|
||||
|
||||
PsiTypeElement typeElement = myMethod.getReturnTypeElement();
|
||||
final PsiType returnType = typeElement == null ? null : typeElement.getType();
|
||||
return ContainerUtil.filter(doInferContracts(), new Condition<MethodContract>() {
|
||||
final boolean notNull = !(returnType instanceof PsiPrimitiveType) &&
|
||||
NullableNotNullManager.getInstance(myMethod.getProject()).isNotNull(myMethod, false);
|
||||
return ContainerUtil.filter(contracts, new Condition<MethodContract>() {
|
||||
@Override
|
||||
public boolean value(MethodContract contract) {
|
||||
if (notNull && contract.returnValue == NOT_NULL_VALUE) {
|
||||
|
||||
@@ -448,12 +448,15 @@ public class JavaCompletionUtil {
|
||||
PsiSubstitutor plainSub = plainResult.getSubstitutor();
|
||||
PsiSubstitutor castSub = TypeConversionUtil.getSuperClassSubstitutor(plainClass, (PsiClassType)castType);
|
||||
PsiType returnType = method.getReturnType();
|
||||
if (method.getSignature(plainSub).equals(method.getSignature(castSub)) &&
|
||||
returnType != null &&
|
||||
toRaw(castSub.substitute(returnType)).isAssignableFrom(toRaw(plainSub.substitute(returnType))) &&
|
||||
processor.isAccessible(plainClass.findMethodBySignature(method, true))
|
||||
) {
|
||||
return item;
|
||||
if (method.getSignature(plainSub).equals(method.getSignature(castSub))) {
|
||||
PsiType typeAfterCast = toRaw(castSub.substitute(returnType));
|
||||
PsiType typeDeclared = toRaw(plainSub.substitute(returnType));
|
||||
if (typeAfterCast != null && typeDeclared != null &&
|
||||
typeAfterCast.isAssignableFrom(typeDeclared) &&
|
||||
processor.isAccessible(plainClass.findMethodBySignature(method, true))
|
||||
) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -495,7 +498,8 @@ public class JavaCompletionUtil {
|
||||
});
|
||||
}
|
||||
|
||||
private static PsiType toRaw(@NotNull PsiType type) {
|
||||
@Nullable
|
||||
private static PsiType toRaw(@Nullable PsiType type) {
|
||||
return type instanceof PsiClassType ? ((PsiClassType)type).rawType() : type;
|
||||
}
|
||||
|
||||
|
||||
@@ -565,8 +565,14 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
|
||||
@NotNull
|
||||
public static CharSequence decompile(@NotNull VirtualFile file) {
|
||||
PsiManager manager = PsiManager.getInstance(DefaultProjectFactory.getInstance().getDefaultProject());
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
new ClsFileImpl(new ClassFileViewProvider(manager, file), true).appendMirrorText(0, buffer);
|
||||
final ClsFileImpl clsFile = new ClsFileImpl(new ClassFileViewProvider(manager, file), true);
|
||||
final StringBuilder buffer = new StringBuilder();
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
clsFile.appendMirrorText(0, buffer);
|
||||
}
|
||||
});
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,11 +48,6 @@ public class PersistentRangeMarkerUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rangeMarker.getStartOffset() == rangeMarker.getEndOffset() && e.getOffset() == rangeMarker.getStartOffset() && e.getOldLength() == 0) {
|
||||
//One-point range marker
|
||||
return true;
|
||||
}
|
||||
|
||||
if (e.getOffset() >= rangeMarker.getEndOffset() || e.getOffset() + e.getOldLength() <= rangeMarker.getStartOffset()) {
|
||||
// Don't perform complex processing if the change doesn't affect target range.
|
||||
return false;
|
||||
|
||||
@@ -376,7 +376,10 @@ public class PushController implements Disposable {
|
||||
boolean force) {
|
||||
VcsPushOptionValue options = myDialog.getAdditionalOptionValue(support);
|
||||
Pusher<R, S, T> pusher = support.getPusher();
|
||||
pusher.push(collectPushSpecsForVcs(support), options, force);
|
||||
Map<R, PushSpec<S, T>> specs = collectPushSpecsForVcs(support);
|
||||
if (!specs.isEmpty()) {
|
||||
pusher.push(specs, options, force);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+1
-1
@@ -237,7 +237,7 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementUiComp
|
||||
@NotNull
|
||||
@Override
|
||||
public ArrangementAtomMatchCondition getMatchCondition() {
|
||||
if (myInverted == myCondition.getValue()) {
|
||||
if (Boolean.valueOf(myInverted) == myCondition.getValue()) {
|
||||
if (myOppositeCondition == null) {
|
||||
myOppositeCondition = new ArrangementAtomMatchCondition(myCondition.getType(), !myInverted);
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ public class QuickEditAction implements IntentionAction, LowPriorityAction {
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
DocumentWindow documentWindow = InjectedLanguageUtil.getDocumentWindow(injectedFile);
|
||||
if (documentWindow != null) {
|
||||
handler.navigate(((DocumentWindowImpl)documentWindow).hostToUnescaped(offset));
|
||||
handler.navigate(((DocumentWindowImpl)documentWindow).hostToInjectedUnescaped(offset));
|
||||
}
|
||||
}
|
||||
return handler;
|
||||
|
||||
+2
-1
@@ -340,7 +340,8 @@ public class LiveTemplateSettingsEditor extends JPanel {
|
||||
sb.append(ownName);
|
||||
}
|
||||
final boolean noContexts = sb.length() == 0;
|
||||
ctxLabel.setText((noContexts ? "No applicable contexts" + (allowNoContexts ? "" : " yet") : "Applicable in " + sb.toString()) + ". ");
|
||||
String contexts = (noContexts ? "No applicable contexts" + (allowNoContexts ? "" : " yet") : "Applicable in " + sb.toString()) + ". ";
|
||||
ctxLabel.setText(StringUtil.first(contexts, 100, true));
|
||||
ctxLabel.setForeground(noContexts ? allowNoContexts ? JBColor.GRAY : JBColor.RED : UIUtil.getLabelForeground());
|
||||
change.setText(noContexts ? "Define" : "Change");
|
||||
}
|
||||
|
||||
+22
-11
@@ -31,6 +31,7 @@ import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.openapi.keymap.impl.ui.KeymapPanel;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.options.SchemesManager;
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.options.ex.Settings;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.ui.*;
|
||||
@@ -398,23 +399,25 @@ public class TemplateListPanel extends JPanel implements Disposable {
|
||||
return evt.getPropertyName().equals("ancestor") && evt.getNewValue() != null && evt.getOldValue() == null;
|
||||
}
|
||||
|
||||
private void resizeComboToFitCustomShortcut() {
|
||||
myExpandByCombo.setPrototypeDisplayValue(null);
|
||||
myExpandByCombo.setPrototypeDisplayValue(CUSTOM);
|
||||
}
|
||||
});
|
||||
|
||||
myOpenKeymapLabel.addHyperlinkListener(new HyperlinkAdapter() {
|
||||
@Override
|
||||
protected void hyperlinkActivated(HyperlinkEvent e) {
|
||||
Settings allSettings = Settings.KEY.getData(DataManager.getInstance().getDataContext(myOpenKeymapLabel));
|
||||
final KeymapPanel keymapPanel = allSettings == null ? null : allSettings.find(KeymapPanel.class);
|
||||
if (keymapPanel != null) {
|
||||
allSettings.select(keymapPanel).doWhenDone(new Runnable() {
|
||||
public void run() {
|
||||
keymapPanel.selectAction(IdeActions.ACTION_EXPAND_LIVE_TEMPLATE_CUSTOM);
|
||||
}
|
||||
});
|
||||
final KeymapPanel keymapPanel = allSettings == null ? new KeymapPanel() : allSettings.find(KeymapPanel.class);
|
||||
if (keymapPanel == null) return;
|
||||
|
||||
Runnable selectAction = new Runnable() {
|
||||
public void run() {
|
||||
keymapPanel.selectAction(IdeActions.ACTION_EXPAND_LIVE_TEMPLATE_CUSTOM);
|
||||
}
|
||||
};
|
||||
if (allSettings != null) {
|
||||
allSettings.select(keymapPanel).doWhenDone(selectAction);
|
||||
} else {
|
||||
ShowSettingsUtil.getInstance().editConfigurable(myOpenKeymapLabel, keymapPanel, selectAction);
|
||||
resizeComboToFitCustomShortcut();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -422,6 +425,14 @@ public class TemplateListPanel extends JPanel implements Disposable {
|
||||
return panel;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void resizeComboToFitCustomShortcut() {
|
||||
myExpandByCombo.setPrototypeDisplayValue(null);
|
||||
myExpandByCombo.setPrototypeDisplayValue(CUSTOM);
|
||||
myExpandByCombo.revalidate();
|
||||
myExpandByCombo.repaint();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private TemplateImpl getTemplate(int row) {
|
||||
JTree tree = myTree;
|
||||
|
||||
+9
-6
@@ -701,14 +701,17 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
|
||||
});
|
||||
|
||||
if (results.isEmpty()) {
|
||||
if (commandName != null) {
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (commandName != null) {
|
||||
NOTIFICATION_GROUP.createNotification(InspectionsBundle.message("inspection.no.problems.message"), MessageType.INFO).notify(getProject());
|
||||
}
|
||||
});
|
||||
}
|
||||
if (postRunnable != null) {
|
||||
postRunnable.run();
|
||||
}
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
Runnable runnable = new Runnable() {
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.lang.LanguageUtil;
|
||||
import com.intellij.lang.StdLanguages;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
@@ -33,6 +34,7 @@ import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.ui.EmptyIcon;
|
||||
@@ -63,6 +65,12 @@ public class NewScratchFileAction extends AnAction implements DumbAware {
|
||||
final Project project = e.getProject();
|
||||
if (project == null) return;
|
||||
Language previous = ScratchpadManager.getInstance(project).getLatestLanguage();
|
||||
if (previous == null) {
|
||||
PsiFile file = e.getData(CommonDataKeys.PSI_FILE);
|
||||
if (file != null) {
|
||||
previous = file.getLanguage();
|
||||
}
|
||||
}
|
||||
ListPopup popup = buildLanguagePopup(previous, new Consumer<Language>() {
|
||||
@Override
|
||||
public void consume(Language language) {
|
||||
|
||||
@@ -950,6 +950,17 @@ public abstract class ChooseByNameBase {
|
||||
}
|
||||
|
||||
myAlarm.cancelAllRequests();
|
||||
|
||||
if (delay > 0) {
|
||||
myAlarm.addRequest(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
rebuildList(pos, 0, modalityState, postRunnable);
|
||||
}
|
||||
}, delay, ModalityState.stateForComponent(myTextField));
|
||||
return;
|
||||
}
|
||||
|
||||
myListUpdater.cancelAll();
|
||||
|
||||
final CalcElementsThread calcElementsThread = myCalcElementsThread;
|
||||
@@ -977,32 +988,20 @@ public abstract class ChooseByNameBase {
|
||||
((MatcherHolder)cellRenderer).setPatternMatcher(matcher);
|
||||
}
|
||||
|
||||
final Runnable request = new Runnable() {
|
||||
scheduleCalcElements(text, myCheckBox.isSelected(), modalityState, new Consumer<Set<?>>() {
|
||||
@Override
|
||||
public void run() {
|
||||
scheduleCalcElements(text, myCheckBox.isSelected(), modalityState, new Consumer<Set<?>>() {
|
||||
@Override
|
||||
public void consume(Set<?> elements) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
if (checkDisposed()) {
|
||||
return;
|
||||
}
|
||||
backgroundCalculationFinished(elements, pos);
|
||||
public void consume(Set<?> elements) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
if (checkDisposed()) {
|
||||
return;
|
||||
}
|
||||
backgroundCalculationFinished(elements, pos);
|
||||
|
||||
if (postRunnable != null) {
|
||||
postRunnable.run();
|
||||
}
|
||||
}
|
||||
});
|
||||
if (postRunnable != null) {
|
||||
postRunnable.run();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (delay > 0) {
|
||||
myAlarm.addRequest(request, delay, ModalityState.stateForComponent(myTextField));
|
||||
}
|
||||
else {
|
||||
request.run();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void backgroundCalculationFinished(Collection<?> result, int toSelect) {
|
||||
|
||||
@@ -668,7 +668,7 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
|
||||
}
|
||||
}
|
||||
|
||||
public int hostToUnescaped(int hostOffset) {
|
||||
public int hostToInjectedUnescaped(int hostOffset) {
|
||||
synchronized (myLock) {
|
||||
Segment hostRangeMarker = myShreds.get(0).getHostRangeMarker();
|
||||
if (hostRangeMarker == null || hostOffset < hostRangeMarker.getStartOffset()) return myShreds.get(0).getPrefix().length();
|
||||
|
||||
+3
-6
@@ -15,10 +15,7 @@
|
||||
*/
|
||||
package com.intellij.ide.passwordSafe.config;
|
||||
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.openapi.components.StoragePathMacros;
|
||||
import com.intellij.openapi.components.*;
|
||||
|
||||
/**
|
||||
* The password safe settings
|
||||
@@ -28,8 +25,8 @@ import com.intellij.openapi.components.StoragePathMacros;
|
||||
*/
|
||||
@State(
|
||||
name = "PasswordSafe",
|
||||
storages = {@Storage(
|
||||
file = StoragePathMacros.APP_CONFIG + "/security.xml")})
|
||||
storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/security.xml", roamingType = RoamingType.DISABLED)}
|
||||
)
|
||||
public class PasswordSafeSettings implements PersistentStateComponent<PasswordSafeSettings.State> {
|
||||
/**
|
||||
* The selected provider type
|
||||
|
||||
+3
-6
@@ -17,10 +17,7 @@
|
||||
package com.intellij.ide.passwordSafe.impl.providers.masterKey;
|
||||
|
||||
import com.intellij.ide.passwordSafe.impl.providers.ByteArrayWrapper;
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.openapi.components.StoragePathMacros;
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import org.apache.commons.codec.DecoderException;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
@@ -35,8 +32,8 @@ import java.util.TreeMap;
|
||||
*/
|
||||
@State(
|
||||
name = "PasswordDatabase",
|
||||
storages = {@Storage(
|
||||
file = StoragePathMacros.APP_CONFIG + "/security.xml")})
|
||||
storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/security.xml", roamingType = RoamingType.DISABLED)}
|
||||
)
|
||||
public class PasswordDatabase implements PersistentStateComponent<PasswordDatabase.State> {
|
||||
/**
|
||||
* The name of logger
|
||||
|
||||
+13
-9
@@ -18,6 +18,7 @@ package com.intellij.ide.ui.laf.darcula.ui;
|
||||
import com.intellij.ide.ui.laf.darcula.DarculaUIUtil;
|
||||
import com.intellij.openapi.ui.GraphicsConfig;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.Gray;
|
||||
import com.intellij.util.ui.JBInsets;
|
||||
|
||||
@@ -103,15 +104,18 @@ public class DarculaTextFieldUI extends BasicTextFieldUI {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasText() {
|
||||
JTextComponent component = getComponent();
|
||||
return (component != null) && !StringUtil.isEmpty(component.getText());
|
||||
}
|
||||
|
||||
private SearchAction getActionUnder(MouseEvent e) {
|
||||
final Point cPoint = getClearIconCoord();
|
||||
final Point sPoint = getSearchIconCoord();
|
||||
cPoint.x+=8;
|
||||
cPoint.y+=8;
|
||||
sPoint.x+=8;
|
||||
sPoint.y+=8;
|
||||
final Point ePoint = e.getPoint();
|
||||
return cPoint.distance(ePoint) <= 8 ? SearchAction.CLEAR : sPoint.distance(ePoint) <= 8 ? SearchAction.POPUP : null;
|
||||
Point point = new Point(e.getX() - 8, e.getY() - 8);
|
||||
return point.distance(getSearchIconCoord()) <= 8
|
||||
? SearchAction.POPUP
|
||||
: hasText() && point.distance(getClearIconCoord()) <= 8
|
||||
? SearchAction.CLEAR
|
||||
: null;
|
||||
}
|
||||
|
||||
protected Rectangle getDrawingRect() {
|
||||
@@ -169,7 +173,7 @@ public class DarculaTextFieldUI extends BasicTextFieldUI {
|
||||
searchIcon = IconLoader.findIcon("/com/intellij/ide/ui/laf/icons/search.png", DarculaTextFieldUI.class, true);
|
||||
}
|
||||
searchIcon.paintIcon(null, g, p.x, p.y);
|
||||
if (getComponent().hasFocus() && getComponent().getText().length() > 0) {
|
||||
if (hasText()) {
|
||||
p = getClearIconCoord();
|
||||
Icon clearIcon = UIManager.getIcon("TextField.darcula.clear.icon");
|
||||
if (clearIcon == null) {
|
||||
|
||||
@@ -87,9 +87,7 @@ public class Rediffers {
|
||||
public void beforeDocumentChange(DocumentEvent event) {}
|
||||
|
||||
public void documentChanged(DocumentEvent event) {
|
||||
int newLines = StringUtil.getLineBreakCount(event.getNewFragment());
|
||||
int oldLines = StringUtil.getLineBreakCount(event.getOldFragment());
|
||||
if (newLines != oldLines) myPanel.invalidateDiff();
|
||||
if (event.getOldLength() != event.getNewLength()) myPanel.invalidateDiff();
|
||||
requestRediff();
|
||||
}
|
||||
|
||||
|
||||
+58
-3
@@ -15,9 +15,7 @@
|
||||
*/
|
||||
package com.intellij.ide.bookmarks;
|
||||
|
||||
import com.intellij.openapi.editor.CaretModel;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.LogicalPosition;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.impl.AbstractEditorTest;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
@@ -30,6 +28,7 @@ import org.picocontainer.ComponentAdapter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -91,6 +90,62 @@ public class BookmarkManagerTest extends AbstractEditorTest {
|
||||
delete();
|
||||
assertTrue(getManager().getValidBookmarks().isEmpty());
|
||||
}
|
||||
|
||||
public void testTwoBookmarksOnSameLine1() throws IOException {
|
||||
@NonNls String text =
|
||||
"public class Test {\n" +
|
||||
" public void test() {\n" +
|
||||
" int i = 1;\n" +
|
||||
" int j = 1;\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
init(text, TestFileType.TEXT);
|
||||
|
||||
addBookmark(2);
|
||||
addBookmark(3);
|
||||
List<Bookmark> bookmarksBefore = getManager().getValidBookmarks();
|
||||
assertEquals(2, bookmarksBefore.size());
|
||||
|
||||
myEditor.getCaretModel().setCaretsAndSelections(
|
||||
Collections.singletonList(new CaretState(myEditor.visualToLogicalPosition(new VisualPosition(3, 0)), null, null)));
|
||||
backspace();
|
||||
|
||||
List<Bookmark> bookmarksAfter = getManager().getValidBookmarks();
|
||||
assertEquals(1, bookmarksAfter.size());
|
||||
for (Bookmark bookmark : bookmarksAfter) {
|
||||
checkBookmarkNavigation(bookmark);
|
||||
}
|
||||
}
|
||||
public void testTwoBookmarksOnSameLine2() throws IOException {
|
||||
@NonNls String text =
|
||||
"public class Test {\n" +
|
||||
" public void test() {\n" +
|
||||
" int i = 1;\n" +
|
||||
" int j = 1;\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
init(text, TestFileType.TEXT);
|
||||
|
||||
addBookmark(2);
|
||||
addBookmark(3);
|
||||
List<Bookmark> bookmarksBefore = getManager().getValidBookmarks();
|
||||
assertEquals(2, bookmarksBefore.size());
|
||||
|
||||
myEditor.getCaretModel().setCaretsAndSelections(
|
||||
Collections.singletonList(new CaretState(myEditor.visualToLogicalPosition(new VisualPosition(2, myEditor.getDocument().getLineEndOffset(2)+1)), null, null)));
|
||||
delete();
|
||||
|
||||
List<Bookmark> bookmarksAfter = getManager().getValidBookmarks();
|
||||
assertEquals(1, bookmarksAfter.size());
|
||||
for (Bookmark bookmark : bookmarksAfter) {
|
||||
checkBookmarkNavigation(bookmark);
|
||||
}
|
||||
init(text, TestFileType.TEXT);
|
||||
myEditor.getCaretModel().setCaretsAndSelections(
|
||||
Collections.singletonList(
|
||||
new CaretState(myEditor.visualToLogicalPosition(new VisualPosition(2, myEditor.getDocument().getLineEndOffset(2))), null, null)));
|
||||
delete();
|
||||
}
|
||||
|
||||
public void testBookmarkIsSavedAfterRemoteChange() throws IOException {
|
||||
@NonNls String text =
|
||||
|
||||
@@ -2683,7 +2683,15 @@ public class StringUtil extends StringUtilRt {
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
public static boolean equalsIgnoreWhitespaces(@NotNull CharSequence s1, @NotNull CharSequence s2) {
|
||||
public static boolean equalsIgnoreWhitespaces(@Nullable CharSequence s1, @Nullable CharSequence s2) {
|
||||
if (s1 == null ^ s2 == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (s1 == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int len1 = s1.length();
|
||||
int len2 = s2.length();
|
||||
|
||||
|
||||
@@ -1939,7 +1939,7 @@ public class UIUtil {
|
||||
|
||||
public static Font getTitledBorderFont() {
|
||||
Font defFont = getLabelFont();
|
||||
return defFont.deriveFont(Math.max(defFont.getSize() - 2f, 11f));
|
||||
return defFont.deriveFont(defFont.getSize() - 1f);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3025,7 +3025,7 @@ public class UIUtil {
|
||||
}
|
||||
|
||||
public static Color getSidePanelColor() {
|
||||
return new JBColor(new Color(0xD2D6DD), new Color(60, 68, 71));
|
||||
return new JBColor(0xD2D6DD, 0x3C4447);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.util.text;
|
||||
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
@@ -233,4 +234,51 @@ public class StringUtilTest extends TestCase {
|
||||
public void testReplace() {
|
||||
assertEquals(StringUtil.replace("$PROJECT_FILE$/filename", "$PROJECT_FILE$", "/tmp"), "/tmp/filename");
|
||||
}
|
||||
|
||||
public void testEqualsIgnoreWhitespaces() {
|
||||
assertTrue(StringUtil.equalsIgnoreWhitespaces(null, null));
|
||||
assertFalse(StringUtil.equalsIgnoreWhitespaces("", null));
|
||||
|
||||
assertTrue(StringUtil.equalsIgnoreWhitespaces("", ""));
|
||||
assertTrue(StringUtil.equalsIgnoreWhitespaces("\n\t ", ""));
|
||||
assertTrue(StringUtil.equalsIgnoreWhitespaces("", "\t\n \n\t"));
|
||||
assertTrue(StringUtil.equalsIgnoreWhitespaces("\t", "\n"));
|
||||
|
||||
assertTrue(StringUtil.equalsIgnoreWhitespaces("x", " x"));
|
||||
assertTrue(StringUtil.equalsIgnoreWhitespaces("x", "x "));
|
||||
assertTrue(StringUtil.equalsIgnoreWhitespaces("x\n", "x"));
|
||||
|
||||
assertTrue(StringUtil.equalsIgnoreWhitespaces("abcd", "a\nb\nc\nd\n"));
|
||||
assertTrue(StringUtil.equalsIgnoreWhitespaces("x y x", "x y x"));
|
||||
assertTrue(StringUtil.equalsIgnoreWhitespaces("xyx", "x y x"));
|
||||
|
||||
assertFalse(StringUtil.equalsIgnoreWhitespaces("x", "\t\n "));
|
||||
assertFalse(StringUtil.equalsIgnoreWhitespaces("", " x "));
|
||||
assertFalse(StringUtil.equalsIgnoreWhitespaces("", "x "));
|
||||
assertFalse(StringUtil.equalsIgnoreWhitespaces("", " x"));
|
||||
assertFalse(StringUtil.equalsIgnoreWhitespaces("xyx", "xxx"));
|
||||
assertFalse(StringUtil.equalsIgnoreWhitespaces("xyx", "xYx"));
|
||||
}
|
||||
|
||||
public void testStringHashCodeIgnoreWhitespaces() {
|
||||
assertTrue(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces(""), StringUtil.stringHashCodeIgnoreWhitespaces("")));
|
||||
assertTrue(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("\n\t "), StringUtil.stringHashCodeIgnoreWhitespaces("")));
|
||||
assertTrue(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces(""), StringUtil.stringHashCodeIgnoreWhitespaces("\t\n \n\t")));
|
||||
assertTrue(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("\t"), StringUtil.stringHashCodeIgnoreWhitespaces("\n")));
|
||||
|
||||
assertTrue(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("x"), StringUtil.stringHashCodeIgnoreWhitespaces(" x")));
|
||||
assertTrue(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("x"), StringUtil.stringHashCodeIgnoreWhitespaces("x ")));
|
||||
assertTrue(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("x\n"), StringUtil.stringHashCodeIgnoreWhitespaces("x")));
|
||||
|
||||
assertTrue(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("abcd"), StringUtil.stringHashCodeIgnoreWhitespaces("a\nb\nc\nd\n")));
|
||||
assertTrue(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("x y x"), StringUtil.stringHashCodeIgnoreWhitespaces("x y x")));
|
||||
assertTrue(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("xyx"), StringUtil.stringHashCodeIgnoreWhitespaces("x y x")));
|
||||
|
||||
assertFalse(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("x"), StringUtil.stringHashCodeIgnoreWhitespaces("\t\n ")));
|
||||
assertFalse(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces(""), StringUtil.stringHashCodeIgnoreWhitespaces(" x ")));
|
||||
assertFalse(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces(""), StringUtil.stringHashCodeIgnoreWhitespaces("x ")));
|
||||
assertFalse(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces(""), StringUtil.stringHashCodeIgnoreWhitespaces(" x")));
|
||||
assertFalse(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("xyx"), StringUtil.stringHashCodeIgnoreWhitespaces("xxx")));
|
||||
assertFalse(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("xyx"), StringUtil.stringHashCodeIgnoreWhitespaces("xYx")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
<orderEntry type="library" name="Guava" level="project" />
|
||||
<orderEntry type="module" module-name="lang-impl" />
|
||||
<orderEntry type="module" module-name="spellchecker" />
|
||||
<orderEntry type="library" name="JUnit4" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="JUnit4" level="project" />
|
||||
<orderEntry type="module" module-name="testFramework" scope="TEST" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
</module>
|
||||
@@ -28,8 +28,8 @@ import java.util.TreeMap;
|
||||
*/
|
||||
@State(
|
||||
name = "SSHConnectionSettings",
|
||||
storages = {@Storage(
|
||||
file = StoragePathMacros.APP_CONFIG + "/security.xml")})
|
||||
storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/security.xml", roamingType = RoamingType.DISABLED)}
|
||||
)
|
||||
public class SSHConnectionSettings implements PersistentStateComponent<SSHConnectionSettings.State> {
|
||||
/**
|
||||
* The last successful hosts, the entries are sorted to save on efforts on sorting during saving and loading
|
||||
|
||||
+8
-5
@@ -182,8 +182,8 @@ public class ClassWriter {
|
||||
int start_class_def = buffer.length();
|
||||
writeClassDefinition(node, buffer, indent);
|
||||
|
||||
// count lines in class definition the easiest way
|
||||
total_offset_lines = buffer.substring(start_class_def).toString().split(lineSeparator, -1).length - 1;
|
||||
// // count lines in class definition the easiest way
|
||||
// total_offset_lines = buffer.substring(start_class_def).toString().split(lineSeparator, -1).length - 1;
|
||||
|
||||
boolean hasContent = false;
|
||||
|
||||
@@ -220,6 +220,9 @@ public class ClassWriter {
|
||||
buffer.append(lineSeparator);
|
||||
}
|
||||
|
||||
// FIXME: fields don't matter at the moment
|
||||
total_offset_lines = buffer.substring(start_class_def).toString().split(lineSeparator, -1).length - 1;
|
||||
|
||||
// methods
|
||||
for (StructMethod mt : cl.getMethods()) {
|
||||
boolean hide = mt.isSynthetic() && DecompilerContext.getOption(IFernflowerPreferences.REMOVE_SYNTHETIC) ||
|
||||
@@ -237,7 +240,7 @@ public class ClassWriter {
|
||||
hasContent = true;
|
||||
DecompilerContext.getBytecodeSourceMapper().addTracer(cl.qualifiedName,
|
||||
InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()), method_tracer);
|
||||
total_offset_lines = method_tracer.getCurrentSourceline();
|
||||
total_offset_lines = (method_tracer.getCurrentSourceLine() + 1); // zero-based line index
|
||||
}
|
||||
else {
|
||||
buffer.setLength(position);
|
||||
@@ -805,7 +808,7 @@ public class ClassWriter {
|
||||
if (root != null && !methodWrapper.decompiledWithErrors) { // check for existence
|
||||
try {
|
||||
|
||||
tracer.setCurrentSourceline(buffer.substring(start_index_method).split(lineSeparator, -1).length - 1);
|
||||
tracer.incrementCurrentSourceLine(buffer.substring(start_index_method).split(lineSeparator, -1).length - 1);
|
||||
|
||||
String code = root.toJava(indent + 1, tracer);
|
||||
|
||||
@@ -836,7 +839,7 @@ public class ClassWriter {
|
||||
|
||||
// save total lines
|
||||
// TODO: optimize
|
||||
tracer.setCurrentSourceline(buffer.substring(start_index_method).split(lineSeparator, -1).length - 1);
|
||||
tracer.setCurrentSourceLine(buffer.substring(start_index_method).split(lineSeparator, -1).length - 1);
|
||||
|
||||
return !hideMethod;
|
||||
}
|
||||
|
||||
+2
-1
@@ -268,7 +268,7 @@ public class ClassesProcessor {
|
||||
|
||||
int index = cl.qualifiedName.lastIndexOf("/");
|
||||
if (index >= 0) {
|
||||
total_offset_lines++;
|
||||
total_offset_lines+=2;
|
||||
String packageName = cl.qualifiedName.substring(0, index).replace('/', '.');
|
||||
|
||||
buffer.append("package ");
|
||||
@@ -283,6 +283,7 @@ public class ClassesProcessor {
|
||||
buffer.append(lineSeparator);
|
||||
total_offset_lines += import_lines_written + 1;
|
||||
}
|
||||
//buffer.append(lineSeparator);
|
||||
|
||||
buffer.append(classBuffer);
|
||||
|
||||
|
||||
+21
-4
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.java.decompiler.main.collectors;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
public class BytecodeMappingTracer {
|
||||
@@ -16,14 +17,20 @@ public class BytecodeMappingTracer {
|
||||
current_sourceline = initial_source_line;
|
||||
}
|
||||
|
||||
public void incrementSourceLine() {
|
||||
public void incrementCurrentSourceLine() {
|
||||
current_sourceline++;
|
||||
}
|
||||
|
||||
public void incrementSourceLine(int number_lines) {
|
||||
public void incrementCurrentSourceLine(int number_lines) {
|
||||
current_sourceline += number_lines;
|
||||
}
|
||||
|
||||
public void shiftSourceLines(int shift) {
|
||||
for(Entry<Integer, Integer> entry : mapping.entrySet()) {
|
||||
entry.setValue(entry.getValue() + shift);
|
||||
}
|
||||
}
|
||||
|
||||
public void addMapping(int bytecode_offset) {
|
||||
if(!mapping.containsKey(bytecode_offset)) {
|
||||
mapping.put(bytecode_offset, current_sourceline);
|
||||
@@ -38,15 +45,25 @@ public class BytecodeMappingTracer {
|
||||
}
|
||||
}
|
||||
|
||||
public void addTracer(BytecodeMappingTracer tracer) {
|
||||
if(tracer != null) {
|
||||
for(Entry<Integer, Integer> entry : tracer.mapping.entrySet()) {
|
||||
if(!mapping.containsKey(entry.getKey())) {
|
||||
mapping.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public HashMap<Integer, Integer> getMapping() {
|
||||
return mapping;
|
||||
}
|
||||
|
||||
public int getCurrentSourceline() {
|
||||
public int getCurrentSourceLine() {
|
||||
return current_sourceline;
|
||||
}
|
||||
|
||||
public void setCurrentSourceline(int current_sourceline) {
|
||||
public void setCurrentSourceLine(int current_sourceline) {
|
||||
this.current_sourceline = current_sourceline;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ public class BytecodeSourceMapper {
|
||||
buffer.append(indentstr1 + "method " + method_entry.getKey() + "{" + lineSeparator);
|
||||
|
||||
for(Entry<Integer, Integer> line : method_mapping.entrySet()) {
|
||||
buffer.append(indentstr2 + line.getKey() + indentstr2 + line.getValue() + lineSeparator);
|
||||
buffer.append(indentstr2 + line.getKey() + indentstr2 + (line.getValue() +offset_total) + lineSeparator);
|
||||
}
|
||||
buffer.append(indentstr1 + "}" + lineSeparator);
|
||||
is_first_method = false;
|
||||
|
||||
+3
-3
@@ -778,13 +778,13 @@ public class ExprProcessor implements CodeConstants {
|
||||
buf.append(" label").append(edge.closure.id);
|
||||
}
|
||||
buf.append(";").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
}
|
||||
}
|
||||
|
||||
if (buf.length() == 0 && semicolon) {
|
||||
buf.append(InterpreterUtil.getIndentString(indent)).append(";").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
}
|
||||
|
||||
return buf.toString();
|
||||
@@ -828,7 +828,7 @@ public class ExprProcessor implements CodeConstants {
|
||||
buf.append(";");
|
||||
}
|
||||
buf.append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -124,7 +124,7 @@ public class CatchAllStatement extends Statement {
|
||||
boolean labeled = isLabeled();
|
||||
if (labeled) {
|
||||
buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
}
|
||||
|
||||
List<StatEdge> lstSuccs = first.getSuccessorEdges(STATEDGE_DIRECT_ALL);
|
||||
@@ -137,30 +137,30 @@ public class CatchAllStatement extends Statement {
|
||||
}
|
||||
else {
|
||||
buf.append(indstr).append("try {").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true, tracer));
|
||||
buf.append(indstr).append("}");
|
||||
}
|
||||
|
||||
buf.append(isFinally ? " finally" :
|
||||
" catch (" + vars.get(0).toJava(indent, tracer) + ")").append(" {").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
|
||||
if (monitor != null) {
|
||||
indstr1 = InterpreterUtil.getIndentString(indent + 1);
|
||||
buf.append(indstr1).append("if(").append(monitor.toJava(indent, tracer)).append(") {").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
}
|
||||
|
||||
buf.append(ExprProcessor.jmpWrapper(handler, indent + 1 + (monitor != null ? 1 : 0), true, tracer));
|
||||
|
||||
if (monitor != null) {
|
||||
buf.append(indstr1).append("}").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
}
|
||||
|
||||
buf.append(indstr).append("}").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
+5
-5
@@ -160,11 +160,11 @@ public class CatchStatement extends Statement {
|
||||
|
||||
if (isLabeled()) {
|
||||
buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
}
|
||||
|
||||
buf.append(indstr).append("try {").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
|
||||
buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true, tracer));
|
||||
buf.append(indstr).append("}");
|
||||
@@ -183,14 +183,14 @@ public class CatchStatement extends Statement {
|
||||
}
|
||||
buf.append(vars.get(i - 1).toJava(indent, tracer));
|
||||
buf.append(") {").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
buf.append(ExprProcessor.jmpWrapper(stats.get(i), indent + 1, true, tracer)).append(indstr)
|
||||
.append("}");
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
}
|
||||
buf.append(new_line_separator);
|
||||
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
+9
-9
@@ -102,39 +102,39 @@ public class DoStatement extends Statement {
|
||||
|
||||
if (isLabeled()) {
|
||||
buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
}
|
||||
|
||||
switch (looptype) {
|
||||
case LOOP_DO:
|
||||
buf.append(indstr).append("while(true) {").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true, tracer));
|
||||
buf.append(indstr).append("}").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
break;
|
||||
case LOOP_DOWHILE:
|
||||
buf.append(indstr).append("do {").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true, tracer));
|
||||
buf.append(indstr).append("} while(").append(conditionExprent.get(0).toJava(indent, tracer)).append(");").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
break;
|
||||
case LOOP_WHILE:
|
||||
buf.append(indstr).append("while(").append(conditionExprent.get(0).toJava(indent, tracer)).append(") {").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true, tracer));
|
||||
buf.append(indstr).append("}").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
break;
|
||||
case LOOP_FOR:
|
||||
buf.append(indstr).append("for(").append(initExprent.get(0) == null ? "" : initExprent.get(0).toJava(indent, tracer)).append("; ")
|
||||
.append(conditionExprent.get(0).toJava(indent, tracer)).append("; ").append(incExprent.get(0).toJava(indent, tracer)).append(") {")
|
||||
.append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true, tracer));
|
||||
buf.append(indstr).append("}").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
}
|
||||
|
||||
return buf.toString();
|
||||
|
||||
+10
-6
@@ -211,11 +211,11 @@ public class IfStatement extends Statement {
|
||||
|
||||
if (isLabeled()) {
|
||||
buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
}
|
||||
|
||||
buf.append(indstr).append(headexprent.get(0).toJava(indent, tracer)).append(" {").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
|
||||
if (ifstat == null) {
|
||||
buf.append(InterpreterUtil.getIndentString(indent + 1));
|
||||
@@ -235,7 +235,7 @@ public class IfStatement extends Statement {
|
||||
}
|
||||
}
|
||||
buf.append(";").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
}
|
||||
else {
|
||||
buf.append(ExprProcessor.jmpWrapper(ifstat, indent + 1, true, tracer));
|
||||
@@ -258,11 +258,15 @@ public class IfStatement extends Statement {
|
||||
elseif = true;
|
||||
}
|
||||
else {
|
||||
String content = ExprProcessor.jmpWrapper(elsestat, indent + 1, false, tracer);
|
||||
BytecodeMappingTracer else_tracer = new BytecodeMappingTracer(tracer.getCurrentSourceLine());
|
||||
String content = ExprProcessor.jmpWrapper(elsestat, indent + 1, false, else_tracer);
|
||||
|
||||
if (content.length() > 0) {
|
||||
buf.append(indstr).append("} else {").append(new_line_separator);
|
||||
tracer.incrementSourceLine(); // FIXME: wrong order
|
||||
|
||||
else_tracer.shiftSourceLines(1);
|
||||
tracer.setCurrentSourceLine(else_tracer.getCurrentSourceLine() + 1);
|
||||
tracer.addTracer(else_tracer);
|
||||
|
||||
buf.append(content);
|
||||
}
|
||||
@@ -271,7 +275,7 @@ public class IfStatement extends Statement {
|
||||
|
||||
if (!elseif) {
|
||||
buf.append(indstr).append("}").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
}
|
||||
|
||||
return buf.toString();
|
||||
|
||||
+3
-3
@@ -114,7 +114,7 @@ public class SequenceStatement extends Statement {
|
||||
indstr = InterpreterUtil.getIndentString(indent);
|
||||
indent++;
|
||||
buf.append(indstr).append("label").append(this.id).append(": {").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
}
|
||||
|
||||
boolean notempty = false;
|
||||
@@ -125,7 +125,7 @@ public class SequenceStatement extends Statement {
|
||||
|
||||
if (i > 0 && notempty) {
|
||||
buf.append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
}
|
||||
|
||||
String str = ExprProcessor.jmpWrapper(st, indent, false, tracer);
|
||||
@@ -136,7 +136,7 @@ public class SequenceStatement extends Statement {
|
||||
|
||||
if (islabeled) {
|
||||
buf.append(indstr).append("}").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
}
|
||||
|
||||
return buf.toString();
|
||||
|
||||
+5
-5
@@ -119,11 +119,11 @@ public class SwitchStatement extends Statement {
|
||||
|
||||
if (isLabeled()) {
|
||||
buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
}
|
||||
|
||||
buf.append(indstr).append(headexprent.get(0).toJava(indent, tracer)).append(" {").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
|
||||
VarType switch_type = headexprent.get(0).getExprType();
|
||||
|
||||
@@ -136,14 +136,14 @@ public class SwitchStatement extends Statement {
|
||||
for (int j = 0; j < edges.size(); j++) {
|
||||
if (edges.get(j) == default_edge) {
|
||||
buf.append(indstr).append("default:").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
}
|
||||
else {
|
||||
ConstExprent value = (ConstExprent)values.get(j).copy();
|
||||
value.setConsttype(switch_type);
|
||||
|
||||
buf.append(indstr).append("case ").append(value.toJava(indent, tracer)).append(":").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ public class SwitchStatement extends Statement {
|
||||
}
|
||||
|
||||
buf.append(indstr).append("}").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
+4
-4
@@ -80,17 +80,17 @@ public class SynchronizedStatement extends Statement {
|
||||
|
||||
if (isLabeled()) {
|
||||
buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
}
|
||||
|
||||
buf.append(indstr).append(headexprent.get(0).toJava(indent, tracer)).append(" {").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
|
||||
buf.append(ExprProcessor.jmpWrapper(body, indent + 1, true, tracer));
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
|
||||
buf.append(indstr).append("}").append(new_line_separator);
|
||||
tracer.incrementSourceLine();
|
||||
tracer.incrementCurrentSourceLine();
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
+3
-2
@@ -17,6 +17,7 @@ package org.jetbrains.java.decompiler.struct.attr;
|
||||
|
||||
import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
|
||||
import org.jetbrains.java.decompiler.util.DataInputFullStream;
|
||||
import org.jetbrains.java.decompiler.util.InterpreterUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -29,7 +30,7 @@ import java.io.IOException;
|
||||
* Created by Egor on 05.10.2014.
|
||||
*/
|
||||
public class StructLineNumberTableAttribute extends StructGeneralAttribute {
|
||||
private int[] myLineInfo = new int[0];
|
||||
private int[] myLineInfo = InterpreterUtil.EMPTY_INT_ARRAY;
|
||||
|
||||
@Override
|
||||
public void initContent(ConstantPool pool) throws IOException {
|
||||
@@ -44,7 +45,7 @@ public class StructLineNumberTableAttribute extends StructGeneralAttribute {
|
||||
}
|
||||
}
|
||||
else if (myLineInfo.length > 0) {
|
||||
myLineInfo = new int[0];
|
||||
myLineInfo = InterpreterUtil.EMPTY_INT_ARRAY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -88,6 +88,7 @@ public class FastSparseSetFactory<E> {
|
||||
|
||||
|
||||
public static class FastSparseSet<E> implements Iterable<E> {
|
||||
public static final FastSparseSet[] EMPTY_ARRAY = new FastSparseSet[0];
|
||||
|
||||
private FastSparseSetFactory<E> factory;
|
||||
|
||||
|
||||
+2
@@ -29,6 +29,8 @@ import java.util.zip.ZipFile;
|
||||
public class InterpreterUtil {
|
||||
public static final boolean IS_WINDOWS = System.getProperty("os.name", "").startsWith("Windows");
|
||||
|
||||
public static final int[] EMPTY_INT_ARRAY = new int[0];
|
||||
|
||||
private static final int CHANNEL_WINDOW_SIZE = IS_WINDOWS ? 64 * 1024 * 1024 - (32 * 1024) : 64 * 1024 * 1024; // magic number for Windows
|
||||
private static final int BUFFER_SIZE = 16 * 1024;
|
||||
|
||||
|
||||
+4
-4
@@ -38,9 +38,9 @@ public class SFormsFastMapDirect {
|
||||
private SFormsFastMapDirect(boolean initialize) {
|
||||
if (initialize) {
|
||||
for (int i = 2; i >= 0; i--) {
|
||||
@SuppressWarnings("unchecked") FastSparseSet<Integer>[] empty = new FastSparseSet[0];
|
||||
@SuppressWarnings("unchecked") FastSparseSet<Integer>[] empty = FastSparseSet.EMPTY_ARRAY;
|
||||
elements[i] = empty;
|
||||
next[i] = new int[0];
|
||||
next[i] = InterpreterUtil.EMPTY_INT_ARRAY;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,8 +99,8 @@ public class SFormsFastMapDirect {
|
||||
while (pointer != 0);
|
||||
}
|
||||
else {
|
||||
mapelements[i] = new FastSparseSet[0];
|
||||
mapnext[i] = new int[0];
|
||||
mapelements[i] = FastSparseSet.EMPTY_ARRAY;
|
||||
mapnext[i] = InterpreterUtil.EMPTY_INT_ARRAY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+21
-18
@@ -91,9 +91,7 @@ public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase {
|
||||
}
|
||||
|
||||
public void testNavigation() {
|
||||
String path = PluginPathManager.getPluginHomePath("java-decompiler") + "/testData/Navigation.class";
|
||||
VirtualFile file = StandardFileSystems.local().findFileByPath(path);
|
||||
assertNotNull(path, file);
|
||||
VirtualFile file = getTestFile("Navigation.class");
|
||||
myFixture.openFileInEditor(file);
|
||||
|
||||
doTestNavigation(11, 14, 14, 10); // to "m2()"
|
||||
@@ -101,22 +99,8 @@ public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase {
|
||||
doTestNavigation(16, 28, 15, 13); // to "int r"
|
||||
}
|
||||
|
||||
private void doTestNavigation(int line, int column, int expectedLine, int expectedColumn) {
|
||||
PsiElement target = GotoDeclarationAction.findTargetElement(getProject(), myFixture.getEditor(), offset(line, column));
|
||||
assertTrue(String.valueOf(target), target instanceof Navigatable);
|
||||
((Navigatable)target).navigate(true);
|
||||
int expected = offset(expectedLine, expectedColumn);
|
||||
assertEquals(expected, myFixture.getCaretOffset());
|
||||
}
|
||||
|
||||
private int offset(int line, int column) {
|
||||
return myFixture.getEditor().getDocument().getLineStartOffset(line - 1) + column - 1;
|
||||
}
|
||||
|
||||
public void testHighlighting() {
|
||||
String path = PluginPathManager.getPluginHomePath("java-decompiler") + "/testData/Navigation.class";
|
||||
VirtualFile file = StandardFileSystems.local().findFileByPath(path);
|
||||
assertNotNull(path, file);
|
||||
VirtualFile file = getTestFile("Navigation.class");
|
||||
myFixture.openFileInEditor(file);
|
||||
|
||||
IdentifierHighlighterPassFactory.doWithHighlightingEnabled(new Runnable() {
|
||||
@@ -130,4 +114,23 @@ public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static VirtualFile getTestFile(String name) {
|
||||
String path = PluginPathManager.getPluginHomePath("java-decompiler") + "/plugin/testData/" + name;
|
||||
VirtualFile file = StandardFileSystems.local().findFileByPath(path);
|
||||
assertNotNull(path, file);
|
||||
return file;
|
||||
}
|
||||
|
||||
private void doTestNavigation(int line, int column, int expectedLine, int expectedColumn) {
|
||||
PsiElement target = GotoDeclarationAction.findTargetElement(getProject(), myFixture.getEditor(), offset(line, column));
|
||||
assertTrue(String.valueOf(target), target instanceof Navigatable);
|
||||
((Navigatable)target).navigate(true);
|
||||
int expected = offset(expectedLine, expectedColumn);
|
||||
assertEquals(expected, myFixture.getCaretOffset());
|
||||
}
|
||||
|
||||
private int offset(int line, int column) {
|
||||
return myFixture.getEditor().getDocument().getLineStartOffset(line - 1) + column - 1;
|
||||
}
|
||||
}
|
||||
|
||||
-2
@@ -18,8 +18,6 @@ package org.jetbrains.plugins.javaFX.fxml;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.openapi.application.PluginPathManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
|
||||
import com.intellij.openapi.roots.ContentEntry;
|
||||
import com.intellij.openapi.roots.ModifiableRootModel;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
|
||||
+12
-33
@@ -17,14 +17,13 @@ package org.jetbrains.plugins.javaFX.fxml.codeInsight.intentions;
|
||||
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.OrderEnumerator;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFileFactory;
|
||||
import com.intellij.psi.PsiParserFacade;
|
||||
@@ -36,16 +35,15 @@ import com.intellij.psi.xml.XmlProlog;
|
||||
import com.intellij.ui.components.JBList;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.lang.UrlClassLoader;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineFactory;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
@@ -55,33 +53,14 @@ public class JavaFxInjectPageLanguageIntention extends PsiElementBaseIntentionAc
|
||||
public static final Logger LOG = Logger.getInstance("#" + JavaFxInjectPageLanguageIntention.class.getName());
|
||||
|
||||
private static Set<String> getAvailableLanguages(Project project) {
|
||||
final List<ScriptEngineFactory> engineFactories = new ScriptEngineManager(composeUserClassLoader(project)).getEngineFactories();
|
||||
final List<ScriptEngineFactory> engineFactories = new ScriptEngineManager().getEngineFactories();
|
||||
|
||||
if (engineFactories != null) {
|
||||
final Set<String> availableNames = new TreeSet<String>();
|
||||
for (ScriptEngineFactory factory : engineFactories) {
|
||||
final String engineName = (String)factory.getParameter(ScriptEngine.NAME);
|
||||
availableNames.add(engineName);
|
||||
}
|
||||
return availableNames;
|
||||
final Set<String> availableNames = new TreeSet<String>();
|
||||
for (ScriptEngineFactory factory : engineFactories) {
|
||||
final String engineName = (String)factory.getParameter(ScriptEngine.NAME);
|
||||
availableNames.add(engineName);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static UrlClassLoader composeUserClassLoader(Project project) {
|
||||
final List<URL> urls = new ArrayList<URL>();
|
||||
final List<String> list = OrderEnumerator.orderEntries(project).recursively().runtimeOnly().getPathsList().getPathList();
|
||||
for (String path : list) {
|
||||
try {
|
||||
urls.add(new File(FileUtil.toSystemIndependentName(path)).toURI().toURL());
|
||||
}
|
||||
catch (MalformedURLException e1) {
|
||||
LOG.info(e1);
|
||||
}
|
||||
}
|
||||
|
||||
return UrlClassLoader.build().urls(urls).get();
|
||||
return availableNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -90,7 +69,7 @@ public class JavaFxInjectPageLanguageIntention extends PsiElementBaseIntentionAc
|
||||
final XmlFile containingFile = (XmlFile)element.getContainingFile();
|
||||
|
||||
final Set<String> availableLanguages = getAvailableLanguages(project);
|
||||
if (availableLanguages.size() == 1) {
|
||||
if (availableLanguages.size() == 1 || ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
registerPageLanguage(project, containingFile, availableLanguages.iterator().next());
|
||||
} else {
|
||||
final JBList list = new JBList(availableLanguages);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?language javascript?>
|
||||
<?language groovy?>
|
||||
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<GridPane xmlns:fx="http://javafx.com/fxml">
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
<orderEntry type="module" module-name="python-community" />
|
||||
<orderEntry type="module" module-name="lang-impl" />
|
||||
<orderEntry type="library" name="gson" level="project" />
|
||||
<orderEntry type="library" name="JUnit4" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="JUnit4" level="project" />
|
||||
<orderEntry type="module" module-name="python-ide-community" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
</module>
|
||||
@@ -15,7 +15,7 @@
|
||||
<orderEntry type="library" name="Guava" level="project" />
|
||||
<orderEntry type="library" name="gson" level="project" />
|
||||
<orderEntry type="library" name="markdownj" level="project" />
|
||||
<orderEntry type="library" name="JUnit4" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="JUnit4" level="project" />
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
@@ -26,5 +26,4 @@
|
||||
</library>
|
||||
</orderEntry>
|
||||
</component>
|
||||
</module>
|
||||
|
||||
</module>
|
||||
+21
-18
@@ -33,7 +33,7 @@ import javax.swing.*;
|
||||
/**
|
||||
* @author Dennis.Ushakov
|
||||
*/
|
||||
public class PyDynamicMember {
|
||||
public class PyCustomMember {
|
||||
private String myName;
|
||||
private final boolean myResolveToInstance;
|
||||
private final Function<PsiElement, PyType> myTypeCallback;
|
||||
@@ -45,7 +45,7 @@ public class PyDynamicMember {
|
||||
|
||||
boolean myFunction = false;
|
||||
|
||||
public PyDynamicMember(@NotNull final String name, @Nullable final String type, final boolean resolveToInstance) {
|
||||
public PyCustomMember(@NotNull final String name, @Nullable final String type, final boolean resolveToInstance) {
|
||||
myName = name;
|
||||
myResolveToInstance = resolveToInstance;
|
||||
myTypeName = type;
|
||||
@@ -54,7 +54,7 @@ public class PyDynamicMember {
|
||||
myTypeCallback = null;
|
||||
}
|
||||
|
||||
public PyDynamicMember(@NotNull final String name) {
|
||||
public PyCustomMember(@NotNull final String name) {
|
||||
myName = name;
|
||||
myResolveToInstance = false;
|
||||
myTypeName = null;
|
||||
@@ -63,9 +63,9 @@ public class PyDynamicMember {
|
||||
myTypeCallback = null;
|
||||
}
|
||||
|
||||
public PyDynamicMember(@NotNull final String name,
|
||||
@Nullable final String type,
|
||||
final Function<PsiElement, PyType> typeCallback) {
|
||||
public PyCustomMember(@NotNull final String name,
|
||||
@Nullable final String type,
|
||||
final Function<PsiElement, PyType> typeCallback) {
|
||||
myName = name;
|
||||
|
||||
myResolveToInstance = false;
|
||||
@@ -75,55 +75,58 @@ public class PyDynamicMember {
|
||||
myTypeCallback = typeCallback;
|
||||
}
|
||||
|
||||
public PyDynamicMember(@NotNull final String name, @Nullable final PsiElement target) {
|
||||
public PyCustomMember(@NotNull final String name, @Nullable final PsiElement target, @Nullable String typeName) {
|
||||
myName = name;
|
||||
myTarget = target;
|
||||
myResolveToInstance = false;
|
||||
myTypeName = null;
|
||||
myTypeName = typeName;
|
||||
myTypeCallback = null;
|
||||
}
|
||||
public PyCustomMember(@NotNull final String name, @Nullable final PsiElement target) {
|
||||
this(name, target, null);
|
||||
}
|
||||
|
||||
public PyDynamicMember resolvesTo(String moduleQName) {
|
||||
public PyCustomMember resolvesTo(String moduleQName) {
|
||||
myPsiPath = new PyPsiPath.ToFile(moduleQName);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PyDynamicMember resolvesToClass(String classQName) {
|
||||
public PyCustomMember resolvesToClass(String classQName) {
|
||||
myPsiPath = new PyPsiPath.ToClassQName(classQName);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PyDynamicMember toClass(String name) {
|
||||
public PyCustomMember toClass(String name) {
|
||||
myPsiPath = new PyPsiPath.ToClass(myPsiPath, name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PyDynamicMember toFunction(String name) {
|
||||
public PyCustomMember toFunction(String name) {
|
||||
myPsiPath = new PyPsiPath.ToFunction(myPsiPath, name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PyDynamicMember toFunctionRecursive(String name) {
|
||||
public PyCustomMember toFunctionRecursive(String name) {
|
||||
myPsiPath = new PyPsiPath.ToFunctionRecursive(myPsiPath, name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PyDynamicMember toClassAttribute(String name) {
|
||||
public PyCustomMember toClassAttribute(String name) {
|
||||
myPsiPath = new PyPsiPath.ToClassAttribute(myPsiPath, name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PyDynamicMember toCall(String name, String... args) {
|
||||
public PyCustomMember toCall(String name, String... args) {
|
||||
myPsiPath = new PyPsiPath.ToCall(myPsiPath, name, args);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PyDynamicMember toAssignment(String assignee) {
|
||||
public PyCustomMember toAssignment(String assignee) {
|
||||
myPsiPath = new PyPsiPath.ToAssignment(myPsiPath, assignee);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PyDynamicMember toPsiElement(final PsiElement psiElement) {
|
||||
public PyCustomMember toPsiElement(final PsiElement psiElement) {
|
||||
myPsiPath = new PyPsiPath() {
|
||||
|
||||
@Override
|
||||
@@ -179,7 +182,7 @@ public class PyDynamicMember {
|
||||
return myTypeName.substring(pos + 1);
|
||||
}
|
||||
|
||||
public PyDynamicMember asFunction() {
|
||||
public PyCustomMember asFunction() {
|
||||
myFunction = true;
|
||||
return this;
|
||||
}
|
||||
@@ -110,8 +110,12 @@ public interface PyClass extends PsiNameIdentifierOwner, PyStatement, NameDefine
|
||||
@NotNull
|
||||
PyExpression[] getSuperClassExpressions();
|
||||
|
||||
/**
|
||||
* @param inherited return inherited (parent) methods as well
|
||||
* @return class methods
|
||||
*/
|
||||
@NotNull
|
||||
PyFunction[] getMethods();
|
||||
PyFunction[] getMethods(boolean inherited);
|
||||
|
||||
/**
|
||||
* Get class properties.
|
||||
@@ -243,4 +247,12 @@ public interface PyClass extends PsiNameIdentifierOwner, PyStatement, NameDefine
|
||||
*/
|
||||
@Nullable
|
||||
PyExpression getMetaClassExpression();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param context eval context
|
||||
* @return {@link com.jetbrains.python.psi.types.PyType} casted if it has right type
|
||||
*/
|
||||
@Nullable
|
||||
PyClassLikeType getType(@NotNull TypeEvalContext context);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ import com.jetbrains.python.psi.types.PyType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Function declaration in source (the <code>def</code> and everything within).
|
||||
*
|
||||
@@ -101,4 +103,48 @@ extends
|
||||
|
||||
@Nullable
|
||||
PyAnnotation getAnnotation();
|
||||
|
||||
// TODO: Doc
|
||||
//
|
||||
|
||||
/**
|
||||
* Searches for function attributes.
|
||||
* See <a href="http://legacy.python.org/dev/peps/pep-0232/">PEP-0232</a>
|
||||
* @return assignment statements for function attributes
|
||||
*/
|
||||
@NotNull
|
||||
List<PyAssignmentStatement> findAttributes();
|
||||
|
||||
/**
|
||||
* @return function protection level (underscore based)
|
||||
*/
|
||||
@NotNull
|
||||
ProtectionLevel getProtectionLevel();
|
||||
|
||||
enum ProtectionLevel {
|
||||
/**
|
||||
* public members
|
||||
*/
|
||||
PUBLIC(0),
|
||||
/**
|
||||
* _protected_memebers
|
||||
*/
|
||||
PROTECTED(1),
|
||||
/**
|
||||
* __private_memebrs
|
||||
*/
|
||||
PRIVATE(2);
|
||||
private final int myUnderscoreLevel;
|
||||
|
||||
ProtectionLevel(final int underscoreLevel) {
|
||||
myUnderscoreLevel = underscoreLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return number of underscores
|
||||
*/
|
||||
public int getUnderscoreLevel() {
|
||||
return myUnderscoreLevel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ package com.jetbrains.python.psi.types;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.jetbrains.python.codeInsight.PyDynamicMember;
|
||||
import com.jetbrains.python.codeInsight.PyCustomMember;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -30,7 +30,7 @@ public interface PyClassMembersProvider {
|
||||
ExtensionPointName<PyClassMembersProvider> EP_NAME = ExtensionPointName.create("Pythonid.pyClassMembersProvider");
|
||||
|
||||
@NotNull
|
||||
Collection<PyDynamicMember> getMembers(PyClassType clazz, @Nullable PsiElement location);
|
||||
Collection<PyCustomMember> getMembers(PyClassType clazz, @Nullable PsiElement location);
|
||||
|
||||
@Nullable
|
||||
PsiElement resolveMember(PyClassType clazz, String name, @Nullable PsiElement location);
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
package com.jetbrains.python.psi.types;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.jetbrains.python.codeInsight.PyDynamicMember;
|
||||
import com.jetbrains.python.codeInsight.PyCustomMember;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -30,22 +30,22 @@ import java.util.Collections;
|
||||
public class PyClassMembersProviderBase implements PyClassMembersProvider {
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<PyDynamicMember> getMembers(PyClassType clazz, PsiElement location) {
|
||||
public Collection<PyCustomMember> getMembers(PyClassType clazz, PsiElement location) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement resolveMember(PyClassType clazz, String name, PsiElement location) {
|
||||
final Collection<PyDynamicMember> members = getMembers(clazz, location);
|
||||
final Collection<PyCustomMember> members = getMembers(clazz, location);
|
||||
return resolveMemberByName(members, clazz, name);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement resolveMemberByName(Collection<PyDynamicMember> members,
|
||||
public static PsiElement resolveMemberByName(Collection<PyCustomMember> members,
|
||||
PyClassType clazz,
|
||||
String name) {
|
||||
final PyClass pyClass = clazz.getPyClass();
|
||||
for (PyDynamicMember member : members) {
|
||||
for (PyCustomMember member : members) {
|
||||
if (member.getName().equals(name)) {
|
||||
return member.resolve(pyClass);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ package com.jetbrains.python.psi.types;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.jetbrains.python.codeInsight.PyDynamicMember;
|
||||
import com.jetbrains.python.codeInsight.PyCustomMember;
|
||||
import com.jetbrains.python.psi.PyFile;
|
||||
import com.jetbrains.python.psi.PyPsiFacade;
|
||||
import com.jetbrains.python.psi.resolve.PointInImport;
|
||||
@@ -33,7 +33,7 @@ import java.util.Collections;
|
||||
public abstract class PyModuleMembersProvider {
|
||||
public static final ExtensionPointName<PyModuleMembersProvider> EP_NAME = ExtensionPointName.create("Pythonid.pyModuleMembersProvider");
|
||||
|
||||
public Collection<PyDynamicMember> getMembers(PyFile module, PointInImport point) {
|
||||
public Collection<PyCustomMember> getMembers(PyFile module, PointInImport point) {
|
||||
final VirtualFile vFile = module.getVirtualFile();
|
||||
if (vFile != null) {
|
||||
final String qName = PyPsiFacade.getInstance(module.getProject()).findShortestImportableName(vFile, module);
|
||||
@@ -46,7 +46,7 @@ public abstract class PyModuleMembersProvider {
|
||||
|
||||
@Nullable
|
||||
public PsiElement resolveMember(PyFile module, String name) {
|
||||
for (PyDynamicMember o : getMembers(module, PointInImport.NONE)) {
|
||||
for (PyCustomMember o : getMembers(module, PointInImport.NONE)) {
|
||||
if (o.getName().equals(name)) {
|
||||
return o.resolve(module);
|
||||
}
|
||||
@@ -54,5 +54,5 @@ public abstract class PyModuleMembersProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected abstract Collection<PyDynamicMember> getMembersByQName(PyFile module, String qName);
|
||||
protected abstract Collection<PyCustomMember> getMembersByQName(PyFile module, String qName);
|
||||
}
|
||||
|
||||
@@ -47,8 +47,8 @@ public interface PyType {
|
||||
* or a list of elements that define the name, a la multiResolve().
|
||||
*/
|
||||
@Nullable
|
||||
List<? extends RatedResolveResult> resolveMember(@NotNull final String name, @Nullable PyExpression location,
|
||||
@NotNull AccessDirection direction, @NotNull PyResolveContext resolveContext);
|
||||
List<? extends RatedResolveResult> resolveMember(@NotNull String name, @Nullable final PyExpression location,
|
||||
@NotNull final AccessDirection direction, @NotNull final PyResolveContext resolveContext);
|
||||
|
||||
/**
|
||||
* Proposes completion variants from type's attributes.
|
||||
|
||||
@@ -80,6 +80,7 @@ public class PyTypeProviderBase implements PyTypeProvider {
|
||||
}
|
||||
};
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PyType getReferenceExpressionType(@NotNull PyReferenceExpression referenceExpression, @NotNull TypeEvalContext context) {
|
||||
return null;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.jetbrains.numpy.codeInsight;
|
||||
|
||||
import com.jetbrains.python.codeInsight.PyDynamicMember;
|
||||
import com.jetbrains.python.codeInsight.PyCustomMember;
|
||||
import com.jetbrains.python.psi.PyFile;
|
||||
import com.jetbrains.python.psi.types.PyModuleMembersProvider;
|
||||
|
||||
@@ -39,11 +39,11 @@ public class NumpyModuleMembersProvider extends PyModuleMembersProvider {
|
||||
};
|
||||
|
||||
@Override
|
||||
protected Collection<PyDynamicMember> getMembersByQName(PyFile module, String qName) {
|
||||
protected Collection<PyCustomMember> getMembersByQName(PyFile module, String qName) {
|
||||
if ("numpy".equals(qName)) {
|
||||
final List<PyDynamicMember> members = new ArrayList<PyDynamicMember>();
|
||||
final List<PyCustomMember> members = new ArrayList<PyCustomMember>();
|
||||
for (String type : NUMERIC_TYPES) {
|
||||
members.add(new PyDynamicMember(type, "numpy.core.multiarray.dtype", false));
|
||||
members.add(new PyCustomMember(type, "numpy.core.multiarray.dtype", false));
|
||||
}
|
||||
return members;
|
||||
}
|
||||
|
||||
@@ -846,4 +846,8 @@ remote.interpreter.default.interpreter.path=/usr/bin/python
|
||||
remote.interpreter.unspecified.interpreter.path=Specify Python interpreter path
|
||||
remote.interpreter.unspecified.temp.files.path=Specify path for PyCharm helpers
|
||||
remote.interpreter.configure.path.label=Python interpreter path:
|
||||
remote.interpreter.configure.temp.files.path.label=PyCharm helpers path:
|
||||
remote.interpreter.configure.temp.files.path.label=PyCharm helpers path:
|
||||
|
||||
# Message we display for inspection if user uses custom class type members that do not exist
|
||||
custom.type.name=Dynamic class
|
||||
custom.type.mimic.name=Dynamic class based on {0}
|
||||
@@ -0,0 +1,189 @@
|
||||
package com.jetbrains.python;
|
||||
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.jetbrains.python.codeInsight.PyCustomMember;
|
||||
import com.jetbrains.python.codeInsight.PyCustomMemberUtils;
|
||||
import com.jetbrains.python.psi.AccessDirection;
|
||||
import com.jetbrains.python.psi.PyCallSiteExpression;
|
||||
import com.jetbrains.python.psi.PyExpression;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext;
|
||||
import com.jetbrains.python.psi.resolve.RatedResolveResult;
|
||||
import com.jetbrains.python.psi.types.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Custom (aka dynamic) type that has some members you pass to it. To be used for cases like "type()"
|
||||
* This class can also mimic any other class (optionally). When mimics, it has all methods from this class and its own.
|
||||
* @author Ilya.Kazakevich
|
||||
*/
|
||||
public class PyCustomMembersType implements PyClassLikeType {
|
||||
@NotNull
|
||||
private final Map<String, PyCustomMember> myMembers;
|
||||
@Nullable
|
||||
private final PyClassType myTypeToMimic;
|
||||
|
||||
/**
|
||||
* @param typeToMimic this type may mimic some other class-based type. Pass it to have all members from this class + custom.
|
||||
* Check class manual for more info.
|
||||
* @param members custom members
|
||||
*/
|
||||
public PyCustomMembersType(@Nullable final PyClassType typeToMimic, @NotNull final PyCustomMember... members) {
|
||||
myTypeToMimic = typeToMimic;
|
||||
|
||||
myMembers = new HashMap<String, PyCustomMember>(members.length);
|
||||
for (final PyCustomMember member : members) {
|
||||
myMembers.put(member.getName(), member);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return class we mimic (if any). Check class manual for more info.
|
||||
*/
|
||||
@Nullable
|
||||
public PyClassType getTypeToMimic() {
|
||||
return myTypeToMimic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefinition() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PyClassLikeType toInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getClassQName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<PyClassLikeType> getSuperClassTypes(@NotNull TypeEvalContext context) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<? extends RatedResolveResult> resolveMember(@NotNull final String name,
|
||||
@Nullable final PyExpression location,
|
||||
@NotNull final AccessDirection direction,
|
||||
@NotNull final PyResolveContext resolveContext,
|
||||
final boolean inherited) {
|
||||
if (myMembers.containsKey(name)) {
|
||||
PsiElement context = null;
|
||||
if (location != null) {
|
||||
context = location;
|
||||
}
|
||||
if (context == null) {
|
||||
context = resolveContext.getTypeEvalContext().getOrigin();
|
||||
}
|
||||
if (context != null) {
|
||||
final PsiElement resolveResult = myMembers.get(name).resolve(context);
|
||||
if (resolveResult != null) {
|
||||
return Collections.singletonList(new RatedResolveResult(0, resolveResult));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (myTypeToMimic != null) {
|
||||
return myTypeToMimic.resolveMember(name, location, direction, resolveContext, inherited);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PyClassLikeType getMetaClassType(@NotNull TypeEvalContext context, boolean inherited) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCallable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PyType getReturnType(@NotNull TypeEvalContext context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PyType getCallType(@NotNull TypeEvalContext context, @NotNull PyCallSiteExpression callSite) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<PyCallableParameter> getParameters(@NotNull TypeEvalContext context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<? extends RatedResolveResult> resolveMember(@NotNull final String name,
|
||||
@Nullable final PyExpression location,
|
||||
@NotNull final AccessDirection direction,
|
||||
@NotNull final PyResolveContext resolveContext) {
|
||||
return resolveMember(name, location, direction, resolveContext, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getCompletionVariants(final String completionPrefix, final PsiElement location, final ProcessingContext context) {
|
||||
final Collection<LookupElement> lookupElements = new ArrayList<LookupElement>(myMembers.size());
|
||||
for (final PyCustomMember member : myMembers.values()) {
|
||||
lookupElements.add(PyCustomMemberUtils.toLookUpElement(member, member.getShortType()));
|
||||
}
|
||||
return ArrayUtil.mergeArrays(ArrayUtil.toObjectArray(lookupElements),
|
||||
((myTypeToMimic != null)
|
||||
? myTypeToMimic.getCompletionVariants(completionPrefix, location, context)
|
||||
: PsiElement.EMPTY_ARRAY));
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
String mimicName = null;
|
||||
if (myTypeToMimic != null) {
|
||||
mimicName = myTypeToMimic.getName();
|
||||
}
|
||||
if (mimicName != null) {
|
||||
return PyBundle.message("custom.type.mimic.name", mimicName);
|
||||
}
|
||||
return PyBundle.message("custom.type.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertValid(final String message) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name name to check
|
||||
* @return True if this class (not the one it mimics!) has member with passed name
|
||||
*/
|
||||
public boolean hasMember(@NotNull final String name) {
|
||||
return myMembers.containsKey(name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.jetbrains.python.codeInsight;
|
||||
|
||||
import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* TODO: Move methods to {@link com.jetbrains.python.codeInsight.PyCustomMember}. Only dependency hell prevents me from doing it
|
||||
*/
|
||||
public final class PyCustomMemberUtils {
|
||||
private PyCustomMemberUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates {@link com.intellij.codeInsight.lookup.LookupElement} to be used in cases like {@link com.jetbrains.python.psi.types.PyType#getCompletionVariants(String, com.intellij.psi.PsiElement, com.intellij.util.ProcessingContext)}
|
||||
* This method should be in {@link com.jetbrains.python.codeInsight.PyCustomMember} but it does not. We need to move it.
|
||||
*
|
||||
* @param member custom member
|
||||
* @param typeText type text (if any)
|
||||
* @return lookup element
|
||||
*/
|
||||
@NotNull
|
||||
public static LookupElementBuilder toLookUpElement(@NotNull final PyCustomMember member, @Nullable final String typeText) {
|
||||
|
||||
LookupElementBuilder lookupElementBuilder = LookupElementBuilder.create(member.getName())
|
||||
.withIcon(member.getIcon())
|
||||
.withTypeText(typeText);
|
||||
if (member.isFunction()) {
|
||||
lookupElementBuilder = lookupElementBuilder.withInsertHandler(ParenthesesInsertHandler.NO_PARAMETERS).withLookupString("()");
|
||||
}
|
||||
return lookupElementBuilder;
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ public class PyMethodNavigationOffsetProvider implements MethodNavigationOffsetP
|
||||
array.add(psiElement);
|
||||
}
|
||||
else if (psiElement instanceof PyClass) {
|
||||
Collections.addAll(array, ((PyClass)psiElement).getMethods());
|
||||
Collections.addAll(array, ((PyClass)psiElement).getMethods(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -57,13 +57,13 @@ public class PySuperMethodCompletionContributor extends CompletionContributor {
|
||||
return;
|
||||
}
|
||||
Set<String> seenNames = new HashSet<String>();
|
||||
for (PyFunction function : containingClass.getMethods()) {
|
||||
for (PyFunction function : containingClass.getMethods(false)) {
|
||||
seenNames.add(function.getName());
|
||||
}
|
||||
LanguageLevel languageLevel = LanguageLevel.forElement(parameters.getOriginalFile());
|
||||
seenNames.addAll(PyNames.getBuiltinMethods(languageLevel).keySet());
|
||||
for (PyClass ancestor : containingClass.getAncestorClasses()) {
|
||||
for (PyFunction superMethod : ancestor.getMethods()) {
|
||||
for (PyFunction superMethod : ancestor.getMethods(false)) {
|
||||
if (!seenNames.contains(superMethod.getName())) {
|
||||
String text = superMethod.getName() + superMethod.getParameterList().getText();
|
||||
LookupElementBuilder element = LookupElementBuilder.create(text);
|
||||
|
||||
@@ -281,7 +281,7 @@ public class PyOverrideImplementUtil {
|
||||
public static Collection<PyFunction> getAllSuperFunctions(@NotNull final PyClass pyClass) {
|
||||
final Map<String, PyFunction> superFunctions = new HashMap<String, PyFunction>();
|
||||
for (PyClass aClass : pyClass.getAncestorClasses()) {
|
||||
for (PyFunction function : aClass.getMethods()) {
|
||||
for (PyFunction function : aClass.getMethods(false)) {
|
||||
if (!superFunctions.containsKey(function.getName())) {
|
||||
superFunctions.put(function.getName(), function);
|
||||
}
|
||||
|
||||
+8
-8
@@ -17,7 +17,7 @@ package com.jetbrains.python.codeInsight.stdlib;
|
||||
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.jetbrains.python.codeInsight.PyDynamicMember;
|
||||
import com.jetbrains.python.codeInsight.PyCustomMember;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
import com.jetbrains.python.psi.PyFile;
|
||||
import com.jetbrains.python.psi.PyTargetExpression;
|
||||
@@ -35,16 +35,16 @@ import java.util.List;
|
||||
* @author yole
|
||||
*/
|
||||
public class PyStdlibClassMembersProvider extends PyClassMembersProviderBase {
|
||||
private Key<List<PyDynamicMember>> mySocketMembersKey = Key.create("socket.members");
|
||||
private Key<List<PyCustomMember>> mySocketMembersKey = Key.create("socket.members");
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<PyDynamicMember> getMembers(PyClassType classType, PsiElement location) {
|
||||
public Collection<PyCustomMember> getMembers(PyClassType classType, PsiElement location) {
|
||||
PyClass clazz = classType.getPyClass();
|
||||
final String qualifiedName = clazz.getQualifiedName();
|
||||
if ("socket._socketobject".equals(qualifiedName)) {
|
||||
final PyFile socketFile = (PyFile)clazz.getContainingFile();
|
||||
List<PyDynamicMember> socketMembers = socketFile.getUserData(mySocketMembersKey);
|
||||
List<PyCustomMember> socketMembers = socketFile.getUserData(mySocketMembersKey);
|
||||
if (socketMembers == null) {
|
||||
socketMembers = calcSocketMembers(socketFile);
|
||||
socketFile.putUserData(mySocketMembersKey, socketMembers);
|
||||
@@ -54,20 +54,20 @@ public class PyStdlibClassMembersProvider extends PyClassMembersProviderBase {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private static List<PyDynamicMember> calcSocketMembers(PyFile socketFile) {
|
||||
List<PyDynamicMember> result = new ArrayList<PyDynamicMember>();
|
||||
private static List<PyCustomMember> calcSocketMembers(PyFile socketFile) {
|
||||
List<PyCustomMember> result = new ArrayList<PyCustomMember>();
|
||||
addMethodsFromAttr(socketFile, result, "_socketmethods");
|
||||
addMethodsFromAttr(socketFile, result, "_delegate_methods");
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void addMethodsFromAttr(PyFile socketFile, List<PyDynamicMember> result, final String attrName) {
|
||||
private static void addMethodsFromAttr(PyFile socketFile, List<PyCustomMember> result, final String attrName) {
|
||||
final PyTargetExpression socketMethods = socketFile.findTopLevelAttribute(attrName);
|
||||
if (socketMethods != null) {
|
||||
final List<String> methods = PyUtil.getStringListFromTargetExpression(socketMethods);
|
||||
if (methods != null) {
|
||||
for (String name : methods) {
|
||||
result.add(new PyDynamicMember(name).resolvesTo("_socket").toClass("SocketType").toFunction(name));
|
||||
result.add(new PyCustomMember(name).resolvesTo("_socket").toClass("SocketType").toFunction(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -18,7 +18,7 @@ package com.jetbrains.python.codeInsight.stdlib;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.QualifiedName;
|
||||
import com.jetbrains.python.codeInsight.PyDynamicMember;
|
||||
import com.jetbrains.python.codeInsight.PyCustomMember;
|
||||
import com.jetbrains.python.psi.PyFile;
|
||||
import com.jetbrains.python.psi.resolve.ResolveImportUtil;
|
||||
import com.jetbrains.python.psi.types.PyModuleMembersProvider;
|
||||
@@ -33,15 +33,15 @@ import java.util.List;
|
||||
*/
|
||||
public class PyStdlibModuleMembersProvider extends PyModuleMembersProvider {
|
||||
@Override
|
||||
protected Collection<PyDynamicMember> getMembersByQName(PyFile module, String qName) {
|
||||
protected Collection<PyCustomMember> getMembersByQName(PyFile module, String qName) {
|
||||
if (qName.equals("os")) {
|
||||
final List<PyDynamicMember> results = new ArrayList<PyDynamicMember>();
|
||||
final List<PyCustomMember> results = new ArrayList<PyCustomMember>();
|
||||
PsiElement path = null;
|
||||
if (module != null) {
|
||||
final String pathModuleName = SystemInfo.isWindows ? "ntpath" : "posixpath";
|
||||
path = ResolveImportUtil.resolveModuleInRoots(QualifiedName.fromDottedString(pathModuleName), module);
|
||||
}
|
||||
results.add(new PyDynamicMember("path", path));
|
||||
results.add(new PyCustomMember("path", path));
|
||||
return results;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
|
||||
+8
-8
@@ -16,7 +16,7 @@
|
||||
package com.jetbrains.python.codeInsight.userSkeletons;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.jetbrains.python.codeInsight.PyDynamicMember;
|
||||
import com.jetbrains.python.codeInsight.PyCustomMember;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
import com.jetbrains.python.psi.PyFunction;
|
||||
import com.jetbrains.python.psi.PyTargetExpression;
|
||||
@@ -37,7 +37,7 @@ import java.util.List;
|
||||
public class PyUserSkeletonsClassMembersProvider extends PyClassMembersProviderBase implements PyOverridingAncestorsClassMembersProvider {
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<PyDynamicMember> getMembers(@NotNull PyClassType classType, PsiElement location) {
|
||||
public Collection<PyCustomMember> getMembers(@NotNull PyClassType classType, PsiElement location) {
|
||||
final PyClass cls = classType.getPyClass();
|
||||
final PyClass skeleton = PyUserSkeletonsUtil.getUserSkeleton(cls);
|
||||
if (skeleton != null) {
|
||||
@@ -73,24 +73,24 @@ public class PyUserSkeletonsClassMembersProvider extends PyClassMembersProviderB
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Collection<PyDynamicMember> getClassMembers(@NotNull PyClass cls) {
|
||||
final List<PyDynamicMember> result = new ArrayList<PyDynamicMember>();
|
||||
for (PyFunction function : cls.getMethods()) {
|
||||
private static Collection<PyCustomMember> getClassMembers(@NotNull PyClass cls) {
|
||||
final List<PyCustomMember> result = new ArrayList<PyCustomMember>();
|
||||
for (PyFunction function : cls.getMethods(false)) {
|
||||
final String name = function.getName();
|
||||
if (name != null) {
|
||||
result.add(new PyDynamicMember(name, function));
|
||||
result.add(new PyCustomMember(name, function));
|
||||
}
|
||||
}
|
||||
for (PyTargetExpression attribute : cls.getInstanceAttributes()) {
|
||||
final String name = attribute.getName();
|
||||
if (name != null) {
|
||||
result.add(new PyDynamicMember(name, attribute));
|
||||
result.add(new PyCustomMember(name, attribute));
|
||||
}
|
||||
}
|
||||
for (PyTargetExpression attribute : cls.getClassAttributes()) {
|
||||
final String name = attribute.getName();
|
||||
if (name != null) {
|
||||
result.add(new PyDynamicMember(name, attribute));
|
||||
result.add(new PyCustomMember(name, attribute));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
+4
-4
@@ -17,7 +17,7 @@ package com.jetbrains.python.codeInsight.userSkeletons;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFileSystemItem;
|
||||
import com.jetbrains.python.codeInsight.PyDynamicMember;
|
||||
import com.jetbrains.python.codeInsight.PyCustomMember;
|
||||
import com.jetbrains.python.psi.PyElement;
|
||||
import com.jetbrains.python.psi.PyFile;
|
||||
import com.jetbrains.python.psi.types.PyModuleMembersProvider;
|
||||
@@ -43,17 +43,17 @@ public class PyUserSkeletonsModuleMembersProvider extends PyModuleMembersProvide
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<PyDynamicMember> getMembersByQName(PyFile module, String qName) {
|
||||
protected Collection<PyCustomMember> getMembersByQName(PyFile module, String qName) {
|
||||
final PyFile moduleSkeleton = PyUserSkeletonsUtil.getUserSkeletonForModuleQName(qName, module);
|
||||
if (moduleSkeleton != null) {
|
||||
final List<PyDynamicMember> results = new ArrayList<PyDynamicMember>();
|
||||
final List<PyCustomMember> results = new ArrayList<PyCustomMember>();
|
||||
for (PyElement element : moduleSkeleton.iterateNames()) {
|
||||
if (element instanceof PsiFileSystemItem) {
|
||||
continue;
|
||||
}
|
||||
final String name = element.getName();
|
||||
if (name != null) {
|
||||
results.add(new PyDynamicMember(name, element));
|
||||
results.add(new PyCustomMember(name, element));
|
||||
}
|
||||
}
|
||||
return results;
|
||||
|
||||
@@ -173,7 +173,7 @@ public class DocStringParameterReference extends PsiReferenceBase<PyStringLitera
|
||||
}
|
||||
|
||||
String newName = range.replace(myElement.getText(), newElementName);
|
||||
myElement.updateText(newName);
|
||||
myElement.replace(PyElementGenerator.getInstance(myElement.getProject()).createStringLiteralAlreadyEscaped(newName));
|
||||
return myElement;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ public class PyOldStyleClassesInspection extends PyInspection {
|
||||
registerProblem(attr, "Old-style class contains __slots__ definition", ProblemHighlightType.GENERIC_ERROR_OR_WARNING, null, quickFixes.toArray(new LocalQuickFix[quickFixes.size()]));
|
||||
}
|
||||
}
|
||||
for (PyFunction attr : node.getMethods()) {
|
||||
for (PyFunction attr : node.getMethods(false)) {
|
||||
if ("__getattribute__".equals(attr.getName())) {
|
||||
final ASTNode nameNode = attr.getNameNode();
|
||||
assert nameNode != null;
|
||||
|
||||
@@ -166,7 +166,7 @@ public class AddFieldQuickFix implements LocalQuickFix {
|
||||
appendToMethod(newInit, callback);
|
||||
|
||||
PsiElement addAnchor = null;
|
||||
PyFunction[] meths = cls.getMethods();
|
||||
PyFunction[] meths = cls.getMethods(false);
|
||||
if (meths.length > 0) addAnchor = meths[0].getPrevSibling();
|
||||
PyStatementList clsContent = cls.getStatementList();
|
||||
newInit = (PyFunction) clsContent.addAfter(newInit, addAnchor);
|
||||
|
||||
+27
-5
@@ -33,9 +33,10 @@ import com.intellij.psi.util.QualifiedName;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.PlatformUtils;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.PyCustomMembersType;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
|
||||
import com.jetbrains.python.codeInsight.PyDynamicMember;
|
||||
import com.jetbrains.python.codeInsight.PyCustomMember;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
|
||||
import com.jetbrains.python.codeInsight.imports.AutoImportHintAction;
|
||||
@@ -462,7 +463,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
}
|
||||
if (expr.isQualified()) {
|
||||
final PyClassTypeImpl object_type = (PyClassTypeImpl)PyBuiltinCache.getInstance(node).getObjectType();
|
||||
if ((object_type != null) && object_type.getPossibleInstanceMembers().contains(refName)){
|
||||
if ((object_type != null) && object_type.getPossibleInstanceMembers().contains(refName)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -542,6 +543,10 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
}
|
||||
markedQualified = true;
|
||||
}
|
||||
else if (isHasCustomMember(refName, type)) {
|
||||
// We have dynamic members
|
||||
return;
|
||||
}
|
||||
else {
|
||||
description = PyBundle.message("INSP.cannot.find.$0.in.$1", refText, type.getName());
|
||||
markedQualified = true;
|
||||
@@ -605,6 +610,16 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
registerProblem(node, description, hl_type, null, rangeInElement, actions.toArray(new LocalQuickFix[actions.size()]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if type is custom-member based and has custom member with certain name
|
||||
* @param refName name to check
|
||||
* @param type type
|
||||
* @return true if has one
|
||||
*/
|
||||
private static boolean isHasCustomMember(@NotNull final String refName, @NotNull final PyType type) {
|
||||
return (type instanceof PyCustomMembersType) && ((PyCustomMembersType)type).hasMember(refName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the canonical qualified name for a reference (even for an unresolved one).
|
||||
*/
|
||||
@@ -687,6 +702,13 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (type instanceof PyCustomMembersType) {
|
||||
// Skip custom member types that mimics another class with fuzzy parents
|
||||
PyClassType mimic = ((PyCustomMembersType)type).getTypeToMimic();
|
||||
if (mimic != null && PyUtil.hasUnresolvedAncestors(mimic.getPyClass(), myTypeEvalContext)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (type instanceof PyClassTypeImpl) {
|
||||
PyClass cls = ((PyClassType)type).getPyClass();
|
||||
if (overridesGetAttr(cls, myTypeEvalContext)) {
|
||||
@@ -721,8 +743,8 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
PsiReference reference,
|
||||
@NotNull final String name) {
|
||||
for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) {
|
||||
final Collection<PyDynamicMember> resolveResult = provider.getMembers(type, reference.getElement());
|
||||
for (PyDynamicMember member : resolveResult) {
|
||||
final Collection<PyCustomMember> resolveResult = provider.getMembers(type, reference.getElement());
|
||||
for (PyCustomMember member : resolveResult) {
|
||||
if (member.getName().equals(name)) return true;
|
||||
}
|
||||
}
|
||||
@@ -810,7 +832,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (PyFunction method : containedClass.getMethods()) {
|
||||
for (PyFunction method : containedClass.getMethods(false)) {
|
||||
if (expr.getText().equals(method.getName())) {
|
||||
actions.add(new UnresolvedReferenceAddSelfQuickFix(expr, qualifier));
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class PyElementNode extends BasePsiNode<PyElement> {
|
||||
for (PyClass aClass : pyClass.getNestedClasses()) {
|
||||
result.add(new PyElementNode(myProject, aClass, getSettings()));
|
||||
}
|
||||
for (PyFunction function : pyClass.getMethods()) {
|
||||
for (PyFunction function : pyClass.getMethods(false)) {
|
||||
result.add(new PyElementNode(myProject, function, getSettings()));
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -172,9 +172,7 @@ public class PsiQuery {
|
||||
}
|
||||
}
|
||||
}
|
||||
@SuppressWarnings("unchecked") // Type is preserved
|
||||
final T[] array = (T[])result.toArray(new PsiElement[result.size()]);
|
||||
return new PsiTypedQuery<T>(clazz, array);
|
||||
return new PsiTypedQuery<T>(clazz, result);
|
||||
}
|
||||
|
||||
|
||||
@@ -309,14 +307,17 @@ public class PsiQuery {
|
||||
* Filter elements by class
|
||||
*/
|
||||
@NotNull
|
||||
public PsiQuery filter(@NotNull final Class<? extends PsiElement> clazz) {
|
||||
public <T extends PsiElement> PsiTypedQuery<T> filter(@NotNull final Class<T> clazz) {
|
||||
final Set<PsiElement> result = new HashSet<PsiElement>(Arrays.asList(myPsiElements));
|
||||
for (final PsiElement element : myPsiElements) {
|
||||
if (PyUtil.as(element, clazz) == null) {
|
||||
if (!(clazz.isInstance(element))) {
|
||||
result.remove(element);
|
||||
}
|
||||
}
|
||||
return new PsiQuery(result.toArray(new PsiElement[result.size()]));
|
||||
// We checked it in runtime
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<T> toAdd = (List<T>)new ArrayList<PsiElement>(result);
|
||||
return new PsiTypedQuery<T>(clazz, toAdd);
|
||||
}
|
||||
|
||||
|
||||
@@ -351,16 +352,16 @@ public class PsiQuery {
|
||||
@NotNull
|
||||
private final Class<T> myClass;
|
||||
@NotNull
|
||||
private final T[] myElements;
|
||||
private final List<T> myElements;
|
||||
|
||||
/**
|
||||
* @param clazz type
|
||||
* @param elements elements
|
||||
*/
|
||||
private PsiTypedQuery(@NotNull final Class<T> clazz, @NotNull final T... elements) {
|
||||
private PsiTypedQuery(@NotNull final Class<T> clazz, @NotNull final List<T> elements) {
|
||||
super(elements);
|
||||
myClass = clazz;
|
||||
myElements = elements.clone();
|
||||
myElements = elements;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -383,8 +384,8 @@ public class PsiQuery {
|
||||
* @return All elements of certain type
|
||||
*/
|
||||
@NotNull
|
||||
public T[] getElements() {
|
||||
return myElements.clone();
|
||||
public List<T> getElements() {
|
||||
return Collections.unmodifiableList(myElements);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,9 +389,34 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public PyFunction[] getMethods() {
|
||||
return getClassChildren(PythonDialectsTokenSetProvider.INSTANCE.getFunctionDeclarationTokens(), PyFunction.ARRAY_FACTORY);
|
||||
public PyFunction[] getMethods(final boolean inherited) {
|
||||
final PyFunction[] thisClassFunctions =
|
||||
getClassChildren(PythonDialectsTokenSetProvider.INSTANCE.getFunctionDeclarationTokens(), PyFunction.ARRAY_FACTORY);
|
||||
if (!inherited) {
|
||||
return thisClassFunctions;
|
||||
}
|
||||
// Map to get rid of duplicated (overwritten methods)
|
||||
final Map<String, PyFunction> result = new HashMap<String, PyFunction>();
|
||||
// We get classes in MRO order (hopefully), so last methods are last
|
||||
for (final PyClass superClass : getSuperClasses()) {
|
||||
for (final PyFunction function : superClass.getMethods(false)) {
|
||||
final String functionName = function.getName();
|
||||
if (functionName != null) {
|
||||
result.put(functionName, function);
|
||||
}
|
||||
}
|
||||
}
|
||||
// We now need to add our own methods
|
||||
for (final PyFunction function : thisClassFunctions) {
|
||||
final String functionName = function.getName();
|
||||
if (functionName != null) {
|
||||
result.put(functionName, function);
|
||||
}
|
||||
}
|
||||
final Collection<PyFunction> functionsToReturn = result.values();
|
||||
return functionsToReturn.toArray(new PyFunction[functionsToReturn.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -514,7 +539,7 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
|
||||
// look at @property decorators
|
||||
Map<String, List<PyFunction>> grouped = new HashMap<String, List<PyFunction>>();
|
||||
// group suitable same-named methods, each group defines a property
|
||||
for (PyFunction method : getMethods()) {
|
||||
for (PyFunction method : getMethods(false)) {
|
||||
final String methodName = method.getName();
|
||||
if (name == null || name.equals(methodName)) {
|
||||
List<PyFunction> bucket = grouped.get(methodName);
|
||||
@@ -826,7 +851,7 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
|
||||
public boolean visitMethods(Processor<PyFunction> processor,
|
||||
boolean inherited,
|
||||
boolean skipClassObj) {
|
||||
PyFunction[] methods = getMethods();
|
||||
PyFunction[] methods = getMethods(false);
|
||||
if (!ContainerUtil.process(methods, processor)) return false;
|
||||
if (inherited) {
|
||||
for (PyClass ancestor : getAncestorClasses()) {
|
||||
@@ -932,7 +957,7 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
|
||||
collectInstanceAttributes(initMethod, result);
|
||||
}
|
||||
Set<String> namesInInit = new HashSet<String>(result.keySet());
|
||||
final PyFunction[] methods = getMethods();
|
||||
final PyFunction[] methods = getMethods(false);
|
||||
for (PyFunction method : methods) {
|
||||
if (!PyNames.INIT.equals(method.getName())) {
|
||||
collectInstanceAttributes(method, result, namesInInit);
|
||||
@@ -981,7 +1006,8 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
|
||||
final List<PyTargetExpression> result = new ArrayList<PyTargetExpression>();
|
||||
statementList.accept(new PyRecursiveElementVisitor() {
|
||||
@Override
|
||||
public void visitPyClass(PyClass node) {}
|
||||
public void visitPyClass(PyClass node) {
|
||||
}
|
||||
|
||||
public void visitPyAssignmentStatement(final PyAssignmentStatement node) {
|
||||
for (PyExpression expression : node.getTargets()) {
|
||||
@@ -1338,4 +1364,10 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PyClassLikeType getType(@NotNull TypeEvalContext context) {
|
||||
return PyUtil.as(context.getType(this), PyClassLikeType.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,15 @@ public class PyEvaluator {
|
||||
if (expr instanceof PySequenceExpression) {
|
||||
return evaluateSequenceExpression((PySequenceExpression)expr);
|
||||
}
|
||||
if (expr instanceof PyQualifiedExpression) { // support bool
|
||||
final String referencedName = ((PyQualifiedExpression)expr).getReferencedName();
|
||||
if (PyNames.TRUE.equals(referencedName)) {
|
||||
return true;
|
||||
}
|
||||
if (PyNames.FALSE.equals(referencedName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (expr instanceof PyCallExpression) {
|
||||
return evaluateCall((PyCallExpression)expr);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.StubBasedPsiElement;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
@@ -699,4 +700,39 @@ public class PyFunctionImpl extends PyBaseElementImpl<PyFunctionStub> implements
|
||||
public String getQualifiedName() {
|
||||
return QualifiedNameFinder.getQualifiedName(this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<PyAssignmentStatement> findAttributes() {
|
||||
final List<PyAssignmentStatement> result = new ArrayList<PyAssignmentStatement>();
|
||||
for (final PyAssignmentStatement statement : new PsiQuery(this).siblings(PyAssignmentStatement.class).getElements()) {
|
||||
for (final PyQualifiedExpression targetExpression : new PsiQuery(statement.getTargets()).filter(PyQualifiedExpression.class)
|
||||
.getElements()) {
|
||||
final PyExpression qualifier = targetExpression.getQualifier();
|
||||
if (qualifier == null) {
|
||||
continue;
|
||||
}
|
||||
final PsiReference qualifierReference = qualifier.getReference();
|
||||
if (qualifierReference == null) {
|
||||
continue;
|
||||
}
|
||||
if (qualifierReference.isReferenceTo(this)) {
|
||||
result.add(statement);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ProtectionLevel getProtectionLevel() {
|
||||
final int underscoreLevels = PyUtil.getInitialUnderscores(getName());
|
||||
for (final ProtectionLevel level : ProtectionLevel.values()) {
|
||||
if (level.getUnderscoreLevel() == underscoreLevels) {
|
||||
return level;
|
||||
}
|
||||
}
|
||||
return ProtectionLevel.PRIVATE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package com.jetbrains.python.psi.types;
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionUtil;
|
||||
import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
@@ -33,7 +32,8 @@ import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.codeInsight.PyDynamicMember;
|
||||
import com.jetbrains.python.codeInsight.PyCustomMember;
|
||||
import com.jetbrains.python.codeInsight.PyCustomMemberUtils;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyBuiltinCache;
|
||||
import com.jetbrains.python.psi.impl.ResolveResultList;
|
||||
@@ -151,7 +151,8 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
@NotNull PyResolveContext resolveContext,
|
||||
boolean inherited) {
|
||||
final TypeEvalContext context = resolveContext.getTypeEvalContext();
|
||||
PsiElement classMember = resolveByOverridingMembersProviders(this, name, location); //overriding members provers have priority to normal resolve
|
||||
PsiElement classMember =
|
||||
resolveByOverridingMembersProviders(this, name, location); //overriding members provers have priority to normal resolve
|
||||
if (classMember != null) {
|
||||
return ResolveResultList.to(classMember);
|
||||
}
|
||||
@@ -219,7 +220,8 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
}
|
||||
|
||||
if (inherited) {
|
||||
classMember = resolveByMembersProviders(this, name, location); //ask providers after real class introspection as providers have less priority
|
||||
classMember =
|
||||
resolveByMembersProviders(this, name, location); //ask providers after real class introspection as providers have less priority
|
||||
}
|
||||
|
||||
if (classMember != null) {
|
||||
@@ -414,16 +416,11 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
addInheritedMembers(prefix, location, namesAlready, context, ret, typeEvalContext);
|
||||
|
||||
// from providers
|
||||
for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) {
|
||||
for (PyDynamicMember member : provider.getMembers(this, location)) {
|
||||
for (final PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) {
|
||||
for (final PyCustomMember member : provider.getMembers(this, location)) {
|
||||
final String name = member.getName();
|
||||
if (!namesAlready.contains(name)) {
|
||||
LookupElementBuilder lookupElementBuilder = LookupElementBuilder.create(name).withIcon(member.getIcon()).withTypeText(getName());
|
||||
if (member.isFunction()) {
|
||||
lookupElementBuilder = lookupElementBuilder.withInsertHandler(ParenthesesInsertHandler.NO_PARAMETERS);
|
||||
lookupElementBuilder.withTailText("()");
|
||||
}
|
||||
ret.add(lookupElementBuilder);
|
||||
ret.add(PyCustomMemberUtils.toLookUpElement(member, getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.codeInsight.PyDynamicMember;
|
||||
import com.jetbrains.python.codeInsight.PyCustomMember;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
|
||||
import com.jetbrains.python.psi.*;
|
||||
@@ -289,7 +289,7 @@ public class PyModuleType implements PyType { // Modules don't descend from obje
|
||||
Set<String> namesAlready = context.get(CTX_NAMES);
|
||||
PointInImport point = ResolveImportUtil.getPointInImport(location);
|
||||
for (PyModuleMembersProvider provider : Extensions.getExtensions(PyModuleMembersProvider.EP_NAME)) {
|
||||
for (PyDynamicMember member : provider.getMembers(myModule, point)) {
|
||||
for (PyCustomMember member : provider.getMembers(myModule, point)) {
|
||||
final String name = member.getName();
|
||||
if (namesAlready != null) {
|
||||
namesAlready.add(name);
|
||||
|
||||
+2
-2
@@ -44,7 +44,7 @@ class MethodsManager extends MembersManager<PyFunction> {
|
||||
|
||||
@Override
|
||||
public boolean hasConflict(@NotNull final PyFunction member, @NotNull final PyClass aClass) {
|
||||
return NamePredicate.hasElementWithSameName(member, Arrays.asList(aClass.getMethods()));
|
||||
return NamePredicate.hasElementWithSameName(member, Arrays.asList(aClass.getMethods(false)));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -64,7 +64,7 @@ class MethodsManager extends MembersManager<PyFunction> {
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<? extends PyElement> getMembersCouldBeMoved(@NotNull final PyClass pyClass) {
|
||||
return FluentIterable.from(Arrays.asList(pyClass.getMethods())).filter(new NamelessFilter<PyFunction>()).filter(NO_PROPERTIES).toList();
|
||||
return FluentIterable.from(Arrays.asList(pyClass.getMethods(false))).filter(new NamelessFilter<PyFunction>()).filter(NO_PROPERTIES).toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -181,7 +181,7 @@ public class PyExtractMethodUtil {
|
||||
scope.add(owner);
|
||||
final PyClass containingClass = ((PyFunction)owner).getContainingClass();
|
||||
if (containingClass != null) {
|
||||
for (PyFunction function : containingClass.getMethods()) {
|
||||
for (PyFunction function : containingClass.getMethods(false)) {
|
||||
if (!function.equals(owner) && !function.equals(generatedMethod))
|
||||
scope.add(function);
|
||||
}
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ public class PythonAtTestConfigurationProducer extends
|
||||
}
|
||||
|
||||
private static boolean hasTestFunction(@NotNull final PyClass pyClass) {
|
||||
PyFunction[] methods = pyClass.getMethods();
|
||||
PyFunction[] methods = pyClass.getMethods(false);
|
||||
for (PyFunction function : methods) {
|
||||
PyDecoratorList decorators = function.getDecoratorList();
|
||||
if (decorators == null) continue;
|
||||
|
||||
@@ -58,7 +58,7 @@ public class PythonDocTestUtil {
|
||||
}
|
||||
|
||||
public static boolean isDocTestClass(PyClass pyClass) {
|
||||
for (PyFunction cls : pyClass.getMethods()) {
|
||||
for (PyFunction cls : pyClass.getMethods(false)) {
|
||||
if (isDocTestFunction(cls)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ public class PyTestUtil {
|
||||
if (className == null) return false;
|
||||
final String name = className.toLowerCase();
|
||||
if (name.startsWith("test")) {
|
||||
for (PyFunction cls : pyClass.getMethods()) {
|
||||
for (PyFunction cls : pyClass.getMethods(false)) {
|
||||
if (isPyTestFunction(cls)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ public class PyControlFlowBuilderTest extends LightMarkedTestCase {
|
||||
configureByFile(testName + ".py");
|
||||
final String fullPath = getTestDataPath() + testName + ".txt";
|
||||
final PyClass pyClass = ((PyFile) myFile).getTopLevelClasses().get(0);
|
||||
final ControlFlow flow = ControlFlowCache.getControlFlow(pyClass.getMethods()[0]);
|
||||
final ControlFlow flow = ControlFlowCache.getControlFlow(pyClass.getMethods(false)[0]);
|
||||
check(fullPath, flow);
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ public class PyControlFlowBuilderTest extends LightMarkedTestCase {
|
||||
configureByFile(testName + ".py");
|
||||
final String fullPath = getTestDataPath() + testName + ".txt";
|
||||
final PyClass pyClass = ((PyFile) myFile).getTopLevelClasses().get(0);
|
||||
final ControlFlow flow = ControlFlowCache.getControlFlow(pyClass.getMethods()[0]);
|
||||
final ControlFlow flow = ControlFlowCache.getControlFlow(pyClass.getMethods(false)[0]);
|
||||
check(fullPath, flow);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ import java.util.Collections;
|
||||
public class PyOverrideTest extends PyTestCase {
|
||||
private void doTest() {
|
||||
myFixture.configureByFile("override/" + getTestName(true) + ".py");
|
||||
PyFunction toOverride = getTopLevelClass(0).getMethods() [0];
|
||||
PyFunction toOverride = getTopLevelClass(0).getMethods(false) [0];
|
||||
PyOverrideImplementUtil.overrideMethods(myFixture.getEditor(), getTopLevelClass(1),
|
||||
Collections.singletonList(new PyMethodMember(toOverride)), false);
|
||||
myFixture.checkResultByFile("override/" + getTestName(true) + "_after.py", true);
|
||||
@@ -86,7 +86,7 @@ public class PyOverrideTest extends PyTestCase {
|
||||
|
||||
public void testInnerClass() { // PY-10976
|
||||
myFixture.configureByFile("override/" + getTestName(true) + ".py");
|
||||
PyFunction toOverride = getTopLevelClass(0).getMethods()[0];
|
||||
PyFunction toOverride = getTopLevelClass(0).getMethods(false)[0];
|
||||
PyClass pyClass = getTopLevelClass(1).getNestedClasses()[0];
|
||||
PyOverrideImplementUtil.overrideMethods(myFixture.getEditor(), pyClass,
|
||||
Collections.singletonList(new PyMethodMember(toOverride)), false);
|
||||
@@ -95,7 +95,7 @@ public class PyOverrideTest extends PyTestCase {
|
||||
|
||||
public void testInnerFunctionClass() {
|
||||
myFixture.configureByFile("override/" + getTestName(true) + ".py");
|
||||
PyFunction toOverride = getTopLevelClass(0).getMethods()[0];
|
||||
PyFunction toOverride = getTopLevelClass(0).getMethods(false)[0];
|
||||
final PsiElement element = myFixture.getElementAtCaret();
|
||||
PyOverrideImplementUtil.overrideMethods(myFixture.getEditor(), PsiTreeUtil.getParentOfType(element, PyClass.class, false),
|
||||
Collections.singletonList(new PyMethodMember(toOverride)), false);
|
||||
@@ -115,7 +115,7 @@ public class PyOverrideTest extends PyTestCase {
|
||||
|
||||
public void testImplement() {
|
||||
myFixture.configureByFile("override/" + getTestName(true) + ".py");
|
||||
PyFunction toImplement = getTopLevelClass(0).getMethods()[1];
|
||||
PyFunction toImplement = getTopLevelClass(0).getMethods(false)[1];
|
||||
PyOverrideImplementUtil.overrideMethods(myFixture.getEditor(), getTopLevelClass(1),
|
||||
Collections.singletonList(new PyMethodMember(toImplement)), true);
|
||||
myFixture.checkResultByFile("override/" + getTestName(true) + "_after.py", true);
|
||||
|
||||
@@ -75,7 +75,7 @@ public class PyStubsTest extends PyTestCase {
|
||||
assertEquals("staticField", attrs.get(0).getName());
|
||||
assertTrue(attrs.get(0).getAssignedQName().matches("deco"));
|
||||
|
||||
final PyFunction[] methods = pyClass.getMethods();
|
||||
final PyFunction[] methods = pyClass.getMethods(false);
|
||||
assertEquals(2, methods.length);
|
||||
assertEquals("__init__", methods [0].getName());
|
||||
assertEquals("fooFunction", methods [1].getName());
|
||||
@@ -122,7 +122,7 @@ public class PyStubsTest extends PyTestCase {
|
||||
Property prop = pyClass.findProperty("value", true);
|
||||
Maybe<Callable> maybe_function = prop.getGetter();
|
||||
assertTrue(maybe_function.isDefined());
|
||||
assertEquals(pyClass.getMethods()[0], maybe_function.value());
|
||||
assertEquals(pyClass.getMethods(false)[0], maybe_function.value());
|
||||
|
||||
Property setvalueProp = pyClass.findProperty("setvalue", true);
|
||||
Maybe<Callable> setter = setvalueProp.getSetter();
|
||||
@@ -135,10 +135,10 @@ public class PyStubsTest extends PyTestCase {
|
||||
prop = pyClass.findProperty("x", true);
|
||||
maybe_function = prop.getGetter();
|
||||
assertTrue(maybe_function.isDefined());
|
||||
assertEquals(pyClass.getMethods()[0], maybe_function.value());
|
||||
assertEquals(pyClass.getMethods(false)[0], maybe_function.value());
|
||||
maybe_function = prop.getSetter();
|
||||
assertTrue(maybe_function.isDefined());
|
||||
assertEquals(pyClass.getMethods()[1], maybe_function.value());
|
||||
assertEquals(pyClass.getMethods(false)[1], maybe_function.value());
|
||||
|
||||
// ...and the juice:
|
||||
assertNotParsed(file);
|
||||
@@ -342,7 +342,7 @@ public class PyStubsTest extends PyTestCase {
|
||||
public void testWrappedStaticMethod() {
|
||||
final PyFileImpl file = (PyFileImpl) getTestFile();
|
||||
final PyClass pyClass = file.getTopLevelClasses().get(0);
|
||||
final PyFunction[] methods = pyClass.getMethods();
|
||||
final PyFunction[] methods = pyClass.getMethods(false);
|
||||
assertEquals(1, methods.length);
|
||||
final PyFunction.Modifier modifier = methods[0].getModifier();
|
||||
assertEquals(PyFunction.Modifier.STATICMETHOD, modifier);
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
package com.jetbrains.python.refactoring.classes;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.text.Matcher;
|
||||
import com.jetbrains.python.fixtures.PyTestCase;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import org.hamcrest.Matchers;
|
||||
@@ -23,7 +22,7 @@ public class PyDependenciesComparatorTest extends PyTestCase {
|
||||
|
||||
@SuppressWarnings("ConstantConditions") // Can't be null (class has docstring)
|
||||
PsiElement docStringExpression = clazz.getDocStringExpression().getParent();
|
||||
PyFunction method = clazz.getMethods()[0];
|
||||
PyFunction method = clazz.getMethods(false)[0];
|
||||
PsiElement classField = clazz.getClassAttributes().get(0).getParent();
|
||||
|
||||
final List<PyStatement> elementList = new ArrayList<PyStatement>();
|
||||
|
||||
@@ -169,6 +169,7 @@ giud
|
||||
globals
|
||||
google
|
||||
gruntfile
|
||||
gulpfile
|
||||
gzip
|
||||
gzipped
|
||||
hamcrest
|
||||
|
||||
Reference in New Issue
Block a user