mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git.labs.intellij.net:idea/community
This commit is contained in:
Generated
-1
@@ -3,7 +3,6 @@
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/lib/jna-utils.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/jna.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/jna-platform.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
|
||||
@@ -1113,6 +1113,11 @@
|
||||
<option name="EFFECT_TYPE" value="-1" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="PY.BUILTIN_NAME">
|
||||
<value>
|
||||
<option name="FOREGROUND" value="8888c6" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="REGEXP.BRACES">
|
||||
<value>
|
||||
<option name="FOREGROUND" value="e8bf6a" />
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.intellij.debugger.impl;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
@@ -23,9 +25,10 @@ import java.io.File;
|
||||
* Time: 2:23:38 PM
|
||||
*/
|
||||
public class HotSwapFile {
|
||||
@NotNull
|
||||
final File file;
|
||||
|
||||
public HotSwapFile(File file) {
|
||||
public HotSwapFile(@NotNull File file) {
|
||||
this.file = file;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +157,12 @@ public class HotSwapManager extends AbstractProjectComponent {
|
||||
private void reloadClasses(DebuggerSession session, Map<String, HotSwapFile> classesToReload, HotSwapProgress progress) {
|
||||
final long newSwapTime = System.currentTimeMillis();
|
||||
new ReloadClassesWorker(session, progress).reloadClasses(classesToReload);
|
||||
setTimeStamp(session, newSwapTime);
|
||||
if (progress.isCancelled()) {
|
||||
session.setModifiedClassesScanRequired(true);
|
||||
}
|
||||
else {
|
||||
setTimeStamp(session, newSwapTime);
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<DebuggerSession, Map<String, HotSwapFile>> findModifiedClasses(List<DebuggerSession> sessions, Map<String, List<String>> generatedPaths) {
|
||||
@@ -220,7 +225,13 @@ public class HotSwapManager extends AbstractProjectComponent {
|
||||
swapProgress.setTitle(DebuggerBundle.message("progress.hotswap.scanning.classes"));
|
||||
scanClassesCommand.run();
|
||||
|
||||
return swapProgress.isCancelled() ? new HashMap<DebuggerSession, Map<String, HotSwapFile>>() : modifiedClasses;
|
||||
if (swapProgress.isCancelled()) {
|
||||
for (DebuggerSession session : sessions) {
|
||||
session.setModifiedClassesScanRequired(true);
|
||||
}
|
||||
return new HashMap<DebuggerSession, Map<String, HotSwapFile>>();
|
||||
}
|
||||
return modifiedClasses;
|
||||
}
|
||||
|
||||
public static void reloadModifiedClasses(final Map<DebuggerSession, Map<String, HotSwapFile>> modifiedClasses, final HotSwapProgress reloadClassesProgress) {
|
||||
@@ -240,6 +251,10 @@ public class HotSwapManager extends AbstractProjectComponent {
|
||||
debuggerSession, modifiedClasses.get(debuggerSession), reloadClassesProgress
|
||||
);
|
||||
}
|
||||
|
||||
protected void commandCancelled() {
|
||||
debuggerSession.setModifiedClassesScanRequired(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,11 @@ import com.intellij.debugger.engine.DebugProcessImpl;
|
||||
import com.intellij.debugger.engine.events.DebuggerCommandImpl;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class MultiProcessCommand implements Runnable{
|
||||
private final List<Pair<DebugProcessImpl, DebuggerCommandImpl>> myCommands = new ArrayList<Pair<DebugProcessImpl, DebuggerCommandImpl>>();
|
||||
private final List<Pair<DebugProcessImpl, DebuggerCommandImpl>> myCommands = new LinkedList<Pair<DebugProcessImpl, DebuggerCommandImpl>>();
|
||||
|
||||
public void run() {
|
||||
while(true) {
|
||||
@@ -40,7 +40,10 @@ public class MultiProcessCommand implements Runnable{
|
||||
|
||||
public void cancel() {
|
||||
synchronized(myCommands) {
|
||||
myCommands.clear();
|
||||
while (!myCommands.isEmpty()) {
|
||||
Pair<DebugProcessImpl, DebuggerCommandImpl> pair = myCommands.remove(0);
|
||||
pair.getSecond().notifyCancelled();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.intellij.util.ui.UIUtil;
|
||||
import com.sun.jdi.ReferenceType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@@ -113,35 +114,44 @@ class ReloadClassesWorker {
|
||||
try {
|
||||
RedefineProcessor redefineProcessor = new RedefineProcessor(virtualMachineProxy);
|
||||
|
||||
int processedClassesCount = 0;
|
||||
for (final String qualifiedName : modifiedClasses.keySet()) {
|
||||
processedClassesCount++;
|
||||
int processedEntriesCount = 0;
|
||||
for (final Map.Entry<String, HotSwapFile> entry : modifiedClasses.entrySet()) {
|
||||
if (redefineProcessor.getProcessedClassesCount() == 0 && myProgress.isCancelled()) {
|
||||
// once at least one class has been actually reloaded, do not interrupt the whole process
|
||||
break;
|
||||
}
|
||||
processedEntriesCount++;
|
||||
final String qualifiedName = entry.getKey();
|
||||
if (qualifiedName != null) {
|
||||
myProgress.setText(qualifiedName);
|
||||
myProgress.setFraction(processedClassesCount / (double)modifiedClasses.size());
|
||||
myProgress.setFraction(processedEntriesCount / (double)modifiedClasses.size());
|
||||
}
|
||||
final HotSwapFile fileDescr = modifiedClasses.get(qualifiedName);
|
||||
final byte[] content;
|
||||
try {
|
||||
content = FileUtil.loadFileBytes(fileDescr.file);
|
||||
redefineProcessor.processClass(qualifiedName, entry.getValue().file);
|
||||
}
|
||||
catch (IOException e) {
|
||||
reportProblem(qualifiedName, e);
|
||||
continue;
|
||||
}
|
||||
redefineProcessor.processClass(qualifiedName, content);
|
||||
}
|
||||
|
||||
if (redefineProcessor.getProcessedClassesCount() == 0 && myProgress.isCancelled()) {
|
||||
// once at least one class has been actually reloaded, do not interrupt the whole process
|
||||
return;
|
||||
}
|
||||
|
||||
redefineProcessor.processPending();
|
||||
myProgress.setFraction(1);
|
||||
|
||||
final int partiallyRedefinedClassesCount = redefineProcessor.getPartiallyRedefinedClassesCount();
|
||||
if (partiallyRedefinedClassesCount == 0) {
|
||||
myProgress.addMessage(myDebuggerSession, MessageCategory.INFORMATION,
|
||||
DebuggerBundle.message("status.classes.reloaded", redefineProcessor.getProcessedClassesCount()));
|
||||
myProgress.addMessage(
|
||||
myDebuggerSession, MessageCategory.INFORMATION, DebuggerBundle.message("status.classes.reloaded", redefineProcessor.getProcessedClassesCount())
|
||||
);
|
||||
}
|
||||
else {
|
||||
final String message = DebuggerBundle.message("status.classes.not.all.versions.reloaded", partiallyRedefinedClassesCount,
|
||||
redefineProcessor.getProcessedClassesCount());
|
||||
final String message = DebuggerBundle.message(
|
||||
"status.classes.not.all.versions.reloaded", partiallyRedefinedClassesCount, redefineProcessor.getProcessedClassesCount()
|
||||
);
|
||||
myProgress.addMessage(myDebuggerSession, MessageCategory.WARNING, message);
|
||||
}
|
||||
|
||||
@@ -233,10 +243,13 @@ class ReloadClassesWorker {
|
||||
myVirtualMachineProxy = virtualMachineProxy;
|
||||
}
|
||||
|
||||
public void processClass(String qualifiedName, byte[] content) throws Throwable {
|
||||
public void processClass(String qualifiedName, File file) throws Throwable {
|
||||
final List<ReferenceType> vmClasses = myVirtualMachineProxy.classesByName(qualifiedName);
|
||||
if (vmClasses.isEmpty()) return;
|
||||
if (vmClasses.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final byte[] content = FileUtil.loadFileBytes(file);
|
||||
if (vmClasses.size() == 1) {
|
||||
myRedefineMap.put(vmClasses.get(0), content);
|
||||
if (myRedefineMap.size() >= CLASSES_CHUNK_SIZE) {
|
||||
|
||||
@@ -269,8 +269,7 @@ public class HotSwapUIImpl extends HotSwapUI implements ProjectComponent {
|
||||
return result.get();
|
||||
}
|
||||
|
||||
private static void reloadModifiedClasses(final Map<DebuggerSession, Map<String, HotSwapFile>> modifiedClasses,
|
||||
final HotSwapProgressImpl progress) {
|
||||
private static void reloadModifiedClasses(final Map<DebuggerSession, Map<String, HotSwapFile>> modifiedClasses, final HotSwapProgressImpl progress) {
|
||||
ProgressManager.getInstance().runProcess(new Runnable() {
|
||||
public void run() {
|
||||
HotSwapManager.reloadModifiedClasses(modifiedClasses, progress);
|
||||
|
||||
+1
-1
@@ -324,7 +324,7 @@ public class HighlightUtil extends HighlightUtilBase {
|
||||
|
||||
static boolean isIntersection(PsiTypeElement castTypeElement, PsiType castType) {
|
||||
if (castType instanceof PsiIntersectionType) return true;
|
||||
return PsiTreeUtil.getChildrenOfType(castTypeElement, PsiTypeElement.class) != null;
|
||||
return castType instanceof PsiClassType && PsiTreeUtil.getChildrenOfType(castTypeElement, PsiTypeElement.class) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.intellij.codeInsight.completion.methodChains;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public final class Constants {
|
||||
|
||||
private Constants() {
|
||||
}
|
||||
|
||||
/**
|
||||
* magic numbers
|
||||
*/
|
||||
public static final int SINGLETON_MAGIC_RATIO = 100;
|
||||
|
||||
public static final int SINGLETON_MAGIC_RATIO2 = 5;
|
||||
|
||||
public static final int CHAIN_SEARCH_MAGIC_RATIO = 12;
|
||||
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
package com.intellij.compilerOutputIndex.impl;
|
||||
|
||||
import com.intellij.codeInsight.completion.methodChains.ChainCompletionStringUtil;
|
||||
import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
|
||||
import org.jetbrains.asm4.ClassReader;
|
||||
import org.jetbrains.asm4.ClassVisitor;
|
||||
import org.jetbrains.asm4.MethodVisitor;
|
||||
import org.jetbrains.asm4.Opcodes;
|
||||
import org.jetbrains.asm4.tree.ClassNode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public class ClassFileData {
|
||||
private final List<MethodData> myMethodDatas;
|
||||
|
||||
public ClassFileData(final ClassNode classNode) {
|
||||
this(classNode, true);
|
||||
}
|
||||
|
||||
public ClassFileData(final ClassNode classNode, final boolean checkForPrimitiveReturn) {
|
||||
myMethodDatas = new ArrayList<MethodData>();
|
||||
classNode.accept(new ClassVisitor(Opcodes.ASM4) {
|
||||
@Override
|
||||
public MethodVisitor visitMethod(final int access,
|
||||
final String name,
|
||||
final String desc,
|
||||
final String signature,
|
||||
final String[] exceptions) {
|
||||
final MethodDataAccumulator methodDataAccumulator = new MethodDataAccumulator(checkForPrimitiveReturn);
|
||||
myMethodDatas.add(methodDataAccumulator.getMethodData());
|
||||
return methodDataAccumulator;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public List<MethodData> getMethodDatas() {
|
||||
return myMethodDatas;
|
||||
}
|
||||
|
||||
public static class MethodData {
|
||||
private final List<MethodInsnSignature> myMethodInsnSignatures = new ArrayList<MethodInsnSignature>();
|
||||
|
||||
private void addSign(final MethodInsnSignature signature) {
|
||||
myMethodInsnSignatures.add(signature);
|
||||
}
|
||||
|
||||
public List<MethodInsnSignature> getMethodInsnSignatures() {
|
||||
return myMethodInsnSignatures;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MethodDataAccumulator extends MethodVisitor {
|
||||
private final MethodData myMethodData = new MethodData();
|
||||
private final boolean myCheckForPrimitiveReturn;
|
||||
|
||||
public MethodDataAccumulator(final boolean checkForPrimitiveReturn) {
|
||||
super(Opcodes.ASM4);
|
||||
myCheckForPrimitiveReturn = checkForPrimitiveReturn;
|
||||
}
|
||||
|
||||
private MethodData getMethodData() {
|
||||
return myMethodData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
|
||||
if (MethodIncompleteSignature.CONSTRUCTOR_METHOD_NAME.equals(name)) {
|
||||
return;
|
||||
}
|
||||
final String ownerClassName = AsmUtil.getQualifiedClassName(owner);
|
||||
if (ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(ownerClassName)) {
|
||||
return;
|
||||
}
|
||||
if (myCheckForPrimitiveReturn) {
|
||||
final String returnType = AsmUtil.getReturnType(desc);
|
||||
if (ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(returnType)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
myMethodData.addSign(new MethodInsnSignature(opcode, owner, name, desc));
|
||||
}
|
||||
}
|
||||
|
||||
public static class MethodInsnSignature {
|
||||
private final int myOpcode;
|
||||
private final String myOwner;
|
||||
private final String myName;
|
||||
private final String myDesc;
|
||||
|
||||
private MethodInsnSignature(final int opcode, final String owner, final String name, final String desc) {
|
||||
myOpcode = opcode;
|
||||
myOwner = owner;
|
||||
myName = name;
|
||||
myDesc = desc;
|
||||
}
|
||||
|
||||
public int getOpcode() {
|
||||
return myOpcode;
|
||||
}
|
||||
|
||||
public String getOwner() {
|
||||
return myOwner;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return myDesc;
|
||||
}
|
||||
}
|
||||
}
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
package com.intellij.compilerOutputIndex.impl;
|
||||
|
||||
import com.google.common.collect.HashMultiset;
|
||||
import com.google.common.collect.Multiset;
|
||||
import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputBaseIndex;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.indexing.StorageException;
|
||||
import com.intellij.util.indexing.ValueContainer;
|
||||
import com.intellij.util.io.KeyDescriptor;
|
||||
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public abstract class CompilerOutputBaseGramsIndex<K> extends CompilerOutputBaseIndex<K, Multiset<MethodIncompleteSignature>> {
|
||||
|
||||
protected CompilerOutputBaseGramsIndex(final KeyDescriptor<K> keyDescriptor, final Project project) {
|
||||
super(keyDescriptor, new GuavaHashMultiSetExternalizer<MethodIncompleteSignature>(MethodIncompleteSignature.createKeyDescriptor()), project);
|
||||
}
|
||||
|
||||
public TreeSet<UsageIndexValue> getValues(final K key) {
|
||||
try {
|
||||
final ValueContainer<Multiset<MethodIncompleteSignature>> valueContainer = myIndex.getData(key);
|
||||
final Multiset<MethodIncompleteSignature> rawValues = HashMultiset.create();
|
||||
valueContainer.forEach(new ValueContainer.ContainerAction<Multiset<MethodIncompleteSignature>>() {
|
||||
@Override
|
||||
public boolean perform(final int id, final Multiset<MethodIncompleteSignature> values) {
|
||||
for (final Multiset.Entry<MethodIncompleteSignature> entry : values.entrySet()) {
|
||||
rawValues.add(entry.getElement(), entry.getCount());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return rawValuesToValues(rawValues);
|
||||
} catch (StorageException e) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
private static TreeSet<UsageIndexValue> rawValuesToValues(final Multiset<MethodIncompleteSignature> rawValues) {
|
||||
final TreeSet<UsageIndexValue> values = new TreeSet<UsageIndexValue>();
|
||||
for (final Multiset.Entry<MethodIncompleteSignature> entry : rawValues.entrySet()) {
|
||||
values.add(new UsageIndexValue(entry.getElement(), entry.getCount()));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.intellij.compilerOutputIndex.impl.bigram;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public class Bigram<E> extends Pair<E, E> {
|
||||
public Bigram(@NotNull final E first, @NotNull final E second) {
|
||||
super(first, second);
|
||||
}
|
||||
|
||||
public Bigram<E> swap() {
|
||||
return new Bigram<E>(second, first);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s - %s", first, second);
|
||||
}
|
||||
}
|
||||
-87
@@ -1,87 +0,0 @@
|
||||
package com.intellij.compilerOutputIndex.impl.bigram;
|
||||
|
||||
import com.google.common.collect.HashMultiset;
|
||||
import com.google.common.collect.Multiset;
|
||||
import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
|
||||
import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
|
||||
import com.intellij.compilerOutputIndex.impl.ClassFileData;
|
||||
import com.intellij.compilerOutputIndex.impl.CompilerOutputBaseGramsIndex;
|
||||
import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
|
||||
import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignatureChain;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.indexing.DataIndexer;
|
||||
import com.intellij.util.indexing.ID;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.asm4.ClassReader;
|
||||
import org.jetbrains.asm4.Opcodes;
|
||||
import org.jetbrains.asm4.tree.ClassNode;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public class BigramMethodsUsageIndex extends CompilerOutputBaseGramsIndex<MethodIncompleteSignature> {
|
||||
public static BigramMethodsUsageIndex getInstance(final Project project) {
|
||||
return CompilerOutputIndexer.getInstance(project).getIndex(BigramMethodsUsageIndex.class);
|
||||
}
|
||||
|
||||
public BigramMethodsUsageIndex( final Project project) {
|
||||
super(MethodIncompleteSignature.createKeyDescriptor(), project);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ID<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>> getIndexId() {
|
||||
return generateIndexId("BigramMethodsUsage");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getVersion() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DataIndexer<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>,ClassNode> getIndexer() {
|
||||
//
|
||||
// not fair way, but works fast
|
||||
//
|
||||
return new DataIndexer<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>, ClassNode>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>> map(final ClassNode inputData) {
|
||||
final Map<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>> map =
|
||||
new HashMap<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>>();
|
||||
for (final ClassFileData.MethodData data : new ClassFileData(inputData).getMethodDatas()) {
|
||||
final SimpleBigramsExtractor extractor = new SimpleBigramsExtractor(new SimpleBigramsExtractor.BigramMethodIncompleteSignatureProcessor() {
|
||||
@Override
|
||||
public void process(final Bigram<MethodIncompleteSignature> bigram) {
|
||||
final MethodIncompleteSignature secondGram = bigram.getSecond();
|
||||
Multiset<MethodIncompleteSignature> occurrences = map.get(secondGram);
|
||||
if (occurrences == null) {
|
||||
occurrences = HashMultiset.create();
|
||||
map.put(secondGram, occurrences);
|
||||
}
|
||||
occurrences.add(bigram.getFirst());
|
||||
}
|
||||
});
|
||||
for (final ClassFileData.MethodInsnSignature ms : data.getMethodInsnSignatures()) {
|
||||
final List<MethodIncompleteSignature> methodInvocations = new SmartList<MethodIncompleteSignature>();
|
||||
final String ownerClassName = AsmUtil.getQualifiedClassName(ms.getOwner());
|
||||
final String returnType = AsmUtil.getReturnType(ms.getDesc());
|
||||
|
||||
if (ms.getName().equals(MethodIncompleteSignature.CONSTRUCTOR_METHOD_NAME)) {
|
||||
methodInvocations.add(MethodIncompleteSignature.constructor(ownerClassName));
|
||||
}
|
||||
else {
|
||||
methodInvocations.add(new MethodIncompleteSignature(ownerClassName, returnType, ms.getName(), ms.getOpcode() == Opcodes.INVOKESTATIC));
|
||||
}
|
||||
extractor.addChain(new MethodIncompleteSignatureChain(methodInvocations));
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
package com.intellij.compilerOutputIndex.impl.bigram;
|
||||
|
||||
import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
|
||||
import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignatureChain;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
class SimpleBigramsExtractor {
|
||||
private final Map<String, MethodIncompleteSignature> myHolder = new HashMap<String, MethodIncompleteSignature>();
|
||||
private final BigramMethodIncompleteSignatureProcessor myProcessor;
|
||||
|
||||
public SimpleBigramsExtractor(final BigramMethodIncompleteSignatureProcessor processor) {
|
||||
myProcessor = processor;
|
||||
}
|
||||
|
||||
public void addChain(final MethodIncompleteSignatureChain chain) {
|
||||
if (chain.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
final MethodIncompleteSignature firstInvocation = chain.getFirstInvocation();
|
||||
assert firstInvocation != null;
|
||||
final MethodIncompleteSignature head = firstInvocation.isStatic() ? null : myHolder.get(firstInvocation.getOwner());
|
||||
for (final Bigram<MethodIncompleteSignature> bigram : toBigrams(head, chain)) {
|
||||
myProcessor.process(bigram);
|
||||
}
|
||||
final MethodIncompleteSignature lastInvocation = chain.getLastInvocation();
|
||||
assert lastInvocation != null;
|
||||
myHolder.put(lastInvocation.getReturnType(), lastInvocation);
|
||||
}
|
||||
|
||||
private static Collection<Bigram<MethodIncompleteSignature>> toBigrams(final @Nullable MethodIncompleteSignature head,
|
||||
final @NotNull MethodIncompleteSignatureChain chain) {
|
||||
MethodIncompleteSignature currentLast = null;
|
||||
if (head != null) {
|
||||
currentLast = head;
|
||||
}
|
||||
final List<Bigram<MethodIncompleteSignature>> bigrams = new ArrayList<Bigram<MethodIncompleteSignature>>(chain.size());
|
||||
for (final MethodIncompleteSignature current : chain.list()) {
|
||||
if (currentLast != null) {
|
||||
bigrams.add(new Bigram<MethodIncompleteSignature>(currentLast, current));
|
||||
}
|
||||
currentLast = current;
|
||||
}
|
||||
return bigrams;
|
||||
}
|
||||
|
||||
public interface BigramMethodIncompleteSignatureProcessor {
|
||||
void process(Bigram<MethodIncompleteSignature> bigram);
|
||||
}
|
||||
}
|
||||
@@ -1661,7 +1661,7 @@ public class JavaDocInfoGenerator {
|
||||
return length;
|
||||
}
|
||||
|
||||
if (type instanceof PsiDisjunctionType) {
|
||||
if (type instanceof PsiDisjunctionType || type instanceof PsiIntersectionType) {
|
||||
if (!generateLink) {
|
||||
final String text = StringUtil.escapeXml(type.getCanonicalText());
|
||||
buffer.append(text);
|
||||
@@ -1669,9 +1669,17 @@ public class JavaDocInfoGenerator {
|
||||
}
|
||||
else {
|
||||
int length = 0;
|
||||
for (PsiType psiType : ((PsiDisjunctionType)type).getDisjunctions()) {
|
||||
final String separator = type instanceof PsiDisjunctionType ? " | " : " & ";
|
||||
final List<PsiType> componentTypes;
|
||||
if (type instanceof PsiIntersectionType) {
|
||||
componentTypes = Arrays.asList(((PsiIntersectionType)type).getConjuncts());
|
||||
}
|
||||
else {
|
||||
componentTypes = ((PsiDisjunctionType)type).getDisjunctions();
|
||||
}
|
||||
for (PsiType psiType : componentTypes) {
|
||||
if (length > 0) {
|
||||
buffer.append(" | ");
|
||||
buffer.append(separator);
|
||||
length += 3;
|
||||
}
|
||||
length += generateType(buffer, psiType, context, generateLink);
|
||||
|
||||
+3
@@ -219,6 +219,9 @@ public class InferenceSession {
|
||||
}
|
||||
}
|
||||
|
||||
for (InferenceVariable inferenceVariable : myInferenceVariables.values()) {
|
||||
inferenceVariable.ignoreInstantiation();
|
||||
}
|
||||
mySiteSubstitutor = resolveBounds(myInferenceVariables.values(), mySiteSubstitutor, true);
|
||||
|
||||
for (InferenceVariable inferenceVariable : myInferenceVariables.values()) {
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
interface PsiManager {
|
||||
|
||||
}
|
||||
interface PsiElement {
|
||||
PsiManager getManager();
|
||||
}
|
||||
interface PsiClass extends PsiElement {
|
||||
}
|
||||
interface PsiMethod extends PsiElement {
|
||||
PsiClass getContainingClass();
|
||||
}
|
||||
interface PsiMethodCallExpression extends PsiElement {
|
||||
PsiMethod resolveMethod();
|
||||
}
|
||||
public class TestCompletion {
|
||||
|
||||
public void method() {
|
||||
PsiManager m = <caret>
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
public class TestIndex {
|
||||
|
||||
public void statMethod(PsiMethodCallExpression e) {
|
||||
e.resolveMethod().getContainingClass().getManager();
|
||||
e.resolveMethod().getContainingClass().getManager();
|
||||
e.resolveMethod().getContainingClass().getManager();
|
||||
e.resolveMethod().getContainingClass().getManager();
|
||||
e.resolveMethod().getContainingClass().getManager();
|
||||
}
|
||||
}
|
||||
interface PsiManager {
|
||||
|
||||
}
|
||||
interface PsiElement {
|
||||
PsiManager getManager();
|
||||
}
|
||||
interface PsiClass extends PsiElement {
|
||||
}
|
||||
interface PsiMethod extends PsiElement {
|
||||
PsiClass getContainingClass();
|
||||
}
|
||||
interface PsiMethodCallExpression extends PsiElement {
|
||||
PsiMethod resolveMethod();
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.patterns
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class VirtualFilePatternsTest extends LightCodeInsightFixtureTestCase {
|
||||
|
||||
public void testWithSuperParent() {
|
||||
def file = myFixture.addFileToProject("foo/bar.txt", "").virtualFile
|
||||
assert PlatformPatterns.virtualFile().withSuperParent(1, PlatformPatterns.virtualFile().withName("foo")).accepts(file)
|
||||
assert !PlatformPatterns.virtualFile().withSuperParent(1, PlatformPatterns.virtualFile().withName("bar")).accepts(file)
|
||||
assert !PlatformPatterns.virtualFile().withSuperParent(2, PlatformPatterns.virtualFile().withName("bar")).accepts(file)
|
||||
assert !PlatformPatterns.virtualFile().withSuperParent(10, PlatformPatterns.virtualFile().withName("bar")).accepts(file)
|
||||
assert !PlatformPatterns.virtualFile().withSuperParent(10, PlatformPatterns.virtualFile().withName("foo")).accepts(file)
|
||||
}
|
||||
}
|
||||
+55
-6
@@ -23,13 +23,13 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Is intended to test formatting in editor behavior, i.e. check how formatting affects things like caret position, selection etc.
|
||||
*
|
||||
* Is intended to test formatting in editor behavior, i.e. check how formatting affects things like caret position, selection etc.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 6/1/11 6:17 PM
|
||||
*/
|
||||
public class JavaFormatterInEditorTest extends LightPlatformCodeInsightTestCase {
|
||||
|
||||
|
||||
public void testCaretPositionOnLongLineWrapping() throws IOException {
|
||||
// Inspired by IDEA-70242
|
||||
getCurrentCodeStyleSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
|
||||
@@ -39,7 +39,7 @@ public class JavaFormatterInEditorTest extends LightPlatformCodeInsightTestCase
|
||||
"\n" +
|
||||
"class <caret>Test {\n" +
|
||||
"}",
|
||||
|
||||
|
||||
"import static java.util.concurrent\n" +
|
||||
" .atomic.AtomicInteger.*;\n" +
|
||||
"\n" +
|
||||
@@ -47,10 +47,59 @@ public class JavaFormatterInEditorTest extends LightPlatformCodeInsightTestCase
|
||||
"}"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public void testCaretPositionPreserved_WhenOnSameLineWithWhiteSpacesOnly() throws IOException {
|
||||
String text = "class Test {\n" +
|
||||
" void test() {\n" +
|
||||
" <caret>\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
doTest(text, text);
|
||||
|
||||
String before = "class Test {\n" +
|
||||
" void test() {\n" +
|
||||
" <caret> \n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
doTest(before, text);
|
||||
}
|
||||
|
||||
public void testCaretPositionPreserved_WhenSomeFormattingNeeded() throws IOException {
|
||||
String before = "public class Test {\n" +
|
||||
" int a;\n" +
|
||||
" \n" +
|
||||
" public static void main(String[] args) {\n" +
|
||||
" <caret>\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" static final long j = 2;\n" +
|
||||
"}";
|
||||
String after = "public class Test {\n" +
|
||||
" int a;\n" +
|
||||
"\n" +
|
||||
" public static void main(String[] args) {\n" +
|
||||
" <caret>\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" static final long j = 2;\n" +
|
||||
"}";
|
||||
doTest(before, after);
|
||||
|
||||
before = "public class Test {\n" +
|
||||
" int a;\n" +
|
||||
" \n" +
|
||||
" public static void main(String[] args) {\n" +
|
||||
" <caret> \n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" static final long j = 2;\n" +
|
||||
"}";
|
||||
doTest(before, after);
|
||||
}
|
||||
|
||||
public void doTest(@NotNull String before, @NotNull String after) throws IOException {
|
||||
configureFromFileText(getTestName(false) + ".java", before);
|
||||
CodeStyleManager.getInstance(getProject()).reformatText(getFile(), 0, getEditor().getDocument().getTextLength());
|
||||
checkResultByText(after);
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -21,7 +21,6 @@ jgoodies-forms.jar
|
||||
jgoodies-looks-2.4.2.jar
|
||||
jh.jar
|
||||
jna-utils.jar
|
||||
jna-platform.jar
|
||||
jna.jar
|
||||
jsch-0.1.50.jar
|
||||
jsr166e.jar
|
||||
|
||||
@@ -118,7 +118,7 @@ public abstract class TreeElementPattern<ParentType, T extends ParentType, Self
|
||||
PairProcessor<ParentType, ProcessingContext> processor) {
|
||||
ParentType parent = t;
|
||||
for (int i = 0; i < level; i++) {
|
||||
if (parent == null) return false;
|
||||
if (parent == null) return true;
|
||||
parent = getParent(parent);
|
||||
}
|
||||
return processor.process(parent, context);
|
||||
|
||||
@@ -259,13 +259,13 @@ public class PsiTreeUtil {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T extends PsiElement> Collection<T> findChildrenOfType(@Nullable PsiElement element, @NotNull Class<T> aClass) {
|
||||
public static <T extends PsiElement> Collection<T> findChildrenOfType(@Nullable PsiElement element, @NotNull Class<? extends T> aClass) {
|
||||
return findChildrenOfAnyType(element, aClass);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T extends PsiElement> Collection<T> findChildrenOfAnyType(@Nullable final PsiElement element,
|
||||
@NotNull final Class<T>... classes) {
|
||||
@NotNull final Class<? extends T>... classes) {
|
||||
if (element == null) {
|
||||
return ContainerUtil.emptyList();
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 703 B After Width: | Height: | Size: 571 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
@@ -27,24 +27,26 @@ import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.ui.DocumentAdapter;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.ui.ListSpeedSearch;
|
||||
import com.intellij.ui.components.JBCheckBox;
|
||||
import com.intellij.ui.components.JBList;
|
||||
import com.intellij.ui.components.JBMovePanel;
|
||||
import com.intellij.util.EventDispatcher;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import com.intellij.util.ui.GridBag;
|
||||
import com.intellij.util.ReflectionUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.plaf.basic.ComboPopup;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.*;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class FontOptions extends JPanel implements OptionsPanel{
|
||||
|
||||
@@ -55,162 +57,95 @@ public class FontOptions extends JPanel implements OptionsPanel{
|
||||
|
||||
@NotNull private final ColorAndFontOptions myOptions;
|
||||
|
||||
@NotNull private final DefaultListModel myAllFontsModel = new DefaultListModel();
|
||||
@NotNull private final JBList myAllFontsList = new JBList(myAllFontsModel);
|
||||
@NotNull private final DefaultListModel mySelectedFontsModel = new DefaultListModel();
|
||||
@NotNull private final JBList mySelectedFontsList = new JBList(mySelectedFontsModel);
|
||||
@NotNull private final JBMovePanel myFontsControl = new JBMovePanel(myAllFontsList, mySelectedFontsList) {
|
||||
@SuppressWarnings("SSBasedInspection")
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
super.paint(g);
|
||||
if (myFontNames == null) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
initFontTables();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull private final JTextField myEditorFontSizeField = new MyTextField(4);
|
||||
@NotNull private final JTextField myLineSpacingField = new MyTextField(4);
|
||||
@NotNull private final JTextField myEditorFontSizeField = new JTextField(4);
|
||||
@NotNull private final JTextField myLineSpacingField = new JTextField(4);
|
||||
private final FontNameCombo myPrimaryCombo = new FontNameCombo(null);
|
||||
private final JCheckBox myUseSecondaryFontCheckbox = new JCheckBox(ApplicationBundle.message("secondary.font"));
|
||||
private final FontNameCombo mySecondaryCombo = new FontNameCombo(null);
|
||||
|
||||
@NotNull private final JBCheckBox myOnlyMonospacedCheckBox =
|
||||
new JBCheckBox(ApplicationBundle.message("checkbox.show.only.monospaced.fonts"));
|
||||
@Nullable private final Dimension myPreferredSize;
|
||||
|
||||
private boolean myIsInSchemeChange;
|
||||
private final String myTitle;
|
||||
|
||||
|
||||
public FontOptions(ColorAndFontOptions options) {
|
||||
this(options, ApplicationBundle.message("group.editor.font"));
|
||||
}
|
||||
|
||||
protected FontOptions(@NotNull ColorAndFontOptions options, final String title) {
|
||||
super(new GridBagLayout());
|
||||
setLayout(new MigLayout("ins 0, gap 5, flowx"));
|
||||
Insets borderInsets = new Insets(IdeBorderFactory.TITLED_BORDER_TOP_INSET,
|
||||
IdeBorderFactory.TITLED_BORDER_LEFT_INSET,
|
||||
0,
|
||||
IdeBorderFactory.TITLED_BORDER_RIGHT_INSET);
|
||||
setBorder(IdeBorderFactory.createTitledBorder(title, false, borderInsets));
|
||||
myOptions = options;
|
||||
myTitle = title;
|
||||
add(createEditorFontPanel(), new GridBag().weightx(1).weighty(1).fillCell().coverLine());
|
||||
add(myOnlyMonospacedCheckBox, "sgx b, sx 2");
|
||||
|
||||
add(new JLabel(ApplicationBundle.message("primary.font")), "newline, ax right");
|
||||
add(myPrimaryCombo, "sgx b");
|
||||
add(new JLabel(ApplicationBundle.message("editbox.font.size")), "gapleft 20");
|
||||
add(myEditorFontSizeField);
|
||||
add(new JLabel(ApplicationBundle.message("editbox.line.spacing")), "gapleft 20");
|
||||
add(myLineSpacingField);
|
||||
|
||||
add(new JLabel(ApplicationBundle.message("label.fallback.fonts.list.description"),
|
||||
MessageType.INFO.getDefaultIcon(),
|
||||
SwingConstants.LEFT),
|
||||
new GridBag().anchor(GridBagConstraints.WEST));
|
||||
myFontsControl.setShowButtons(JBMovePanel.ButtonType.LEFT, JBMovePanel.ButtonType.RIGHT);
|
||||
myFontsControl.setListLabels(ApplicationBundle.message("title.font.available"), ApplicationBundle.message("title.font.selected"));
|
||||
myFontsControl.setEnabled(false); // Disable the controls until fonts are loaded.
|
||||
myFontsControl.setLeftInsertionStrategy(JBMovePanel.NATURAL_ORDER);
|
||||
SwingConstants.LEFT), "newline, sx 5");
|
||||
add(myUseSecondaryFontCheckbox, "newline, ax right");
|
||||
add(mySecondaryCombo, "sgx b");
|
||||
|
||||
myOnlyMonospacedCheckBox.setBorder(null);
|
||||
myUseSecondaryFontCheckbox.setBorder(null);
|
||||
mySecondaryCombo.setEnabled(false);
|
||||
|
||||
myOnlyMonospacedCheckBox.setSelected(EditorColorsManager.getInstance().isUseOnlyMonospacedFonts());
|
||||
new ListSpeedSearch(myAllFontsList);
|
||||
new ListSpeedSearch(mySelectedFontsList);
|
||||
|
||||
// Almost all other color scheme pages use the following pattern:
|
||||
//
|
||||
// __________________________________________
|
||||
// | color keys | color and font settings |
|
||||
//
|
||||
// Here page's height is calculated on the 'color and font settings' preferred height (debugged a lot to ensure that).
|
||||
// The idea is to configure current page to use the same height as other pages. That's why we set it up to use the same preferred
|
||||
// size as 'color and font settings' control.
|
||||
myPreferredSize = new ColorAndFontDescriptionPanel().getPreferredSize();
|
||||
if (myFontNames != null) {
|
||||
onFontsInit();
|
||||
}
|
||||
initListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumSize() {
|
||||
return getPreferredSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return myPreferredSize == null ? super.getPreferredSize() : myPreferredSize;
|
||||
}
|
||||
|
||||
private void initListeners() {
|
||||
myOnlyMonospacedCheckBox.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
boolean onlyMonospaced = myOnlyMonospacedCheckBox.isSelected();
|
||||
EditorColorsManager.getInstance().setUseOnlyMonospacedFonts(onlyMonospaced);
|
||||
onFontsInit();
|
||||
EditorColorsManager.getInstance().setUseOnlyMonospacedFonts(myOnlyMonospacedCheckBox.isSelected());
|
||||
myPrimaryCombo.updateModel();
|
||||
mySecondaryCombo.updateModel();
|
||||
}
|
||||
});
|
||||
|
||||
mySelectedFontsModel.addListDataListener(new ListDataListener() {
|
||||
myUseSecondaryFontCheckbox.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void intervalAdded(ListDataEvent e) {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
mySecondaryCombo.setEnabled(myUseSecondaryFontCheckbox.isSelected());
|
||||
syncFontFamilies();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void intervalRemoved(ListDataEvent e) {
|
||||
syncFontFamilies();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contentsChanged(ListDataEvent e) {
|
||||
syncFontFamilies();
|
||||
}
|
||||
|
||||
private void syncFontFamilies() {
|
||||
if (myIsInSchemeChange) {
|
||||
return;
|
||||
}
|
||||
FontPreferences fontPreferences = getFontPreferences();
|
||||
fontPreferences.clearFonts();
|
||||
Enumeration elements = mySelectedFontsModel.elements();
|
||||
while (elements.hasMoreElements()) {
|
||||
String fontFamily = (String)elements.nextElement();
|
||||
// Don't save a single 'default' font family at the font preferences.
|
||||
if (mySelectedFontsModel.getSize() > 1 || !FontPreferences.DEFAULT_FONT_NAME.equals(fontFamily)) {
|
||||
fontPreferences.addFontFamily(fontFamily);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mySelectedFontsList.addListSelectionListener(new ListSelectionListener() {
|
||||
ItemListener itemListener = new ItemListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
Object value = mySelectedFontsList.getSelectedValue();
|
||||
if (value != null) {
|
||||
boolean toRestore = myIsInSchemeChange;
|
||||
myIsInSchemeChange = true;
|
||||
try {
|
||||
myEditorFontSizeField.setText(String.valueOf(getFontPreferences().getSize((String)value)));
|
||||
}
|
||||
finally {
|
||||
myIsInSchemeChange = toRestore;
|
||||
}
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||
syncFontFamilies();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
myPrimaryCombo.addItemListener(itemListener);
|
||||
mySecondaryCombo.addItemListener(itemListener);
|
||||
|
||||
ActionListener actionListener = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
syncFontFamilies();
|
||||
}
|
||||
};
|
||||
myPrimaryCombo.addActionListener(actionListener);
|
||||
mySecondaryCombo.addActionListener(actionListener);
|
||||
|
||||
myEditorFontSizeField.getDocument().addDocumentListener(new DocumentAdapter() {
|
||||
@Override
|
||||
public void textChanged(DocumentEvent event) {
|
||||
if (myIsInSchemeChange || !SwingUtilities.isEventDispatchThread()) return;
|
||||
try {
|
||||
int fontSize = Integer.parseInt(myEditorFontSizeField.getText());
|
||||
if (fontSize < 1) fontSize = 1;
|
||||
if (fontSize > OptionsConstants.MAX_EDITOR_FONT_SIZE) fontSize = OptionsConstants.MAX_EDITOR_FONT_SIZE;
|
||||
Object selectedFont = mySelectedFontsList.getSelectedValue();
|
||||
if (selectedFont != null) {
|
||||
FontPreferences fontPreferences = getFontPreferences();
|
||||
fontPreferences.register((String)selectedFont, fontSize);
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
// OK, ignore
|
||||
}
|
||||
finally {
|
||||
updateDescription(true);
|
||||
Object selectedFont = myPrimaryCombo.getSelectedItem();
|
||||
if (selectedFont instanceof String) {
|
||||
FontPreferences fontPreferences = getFontPreferences();
|
||||
fontPreferences.register((String)selectedFont, getFontSizeFromField());
|
||||
}
|
||||
updateDescription(true);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -218,26 +153,57 @@ public class FontOptions extends JPanel implements OptionsPanel{
|
||||
@Override
|
||||
public void textChanged(DocumentEvent event) {
|
||||
if (myIsInSchemeChange) return;
|
||||
float lineSpacing = 1;
|
||||
try {
|
||||
lineSpacing = Float.parseFloat(myLineSpacingField.getText());
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
// OK, ignore
|
||||
}
|
||||
finally {
|
||||
if (lineSpacing <= 0) lineSpacing = 1;
|
||||
if (lineSpacing > 30) lineSpacing = 30;
|
||||
if (getLineSpacing() != lineSpacing) {
|
||||
setCurrentLineSpacing(lineSpacing);
|
||||
}
|
||||
updateDescription(true);
|
||||
float lineSpacing = getLineSpacingFromField();
|
||||
if (getLineSpacing() != lineSpacing) {
|
||||
setCurrentLineSpacing(lineSpacing);
|
||||
}
|
||||
updateDescription(true);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private int getFontSizeFromField() {
|
||||
try {
|
||||
return Math.min(OptionsConstants.MAX_EDITOR_FONT_SIZE, Math.max(1, Integer.parseInt(myEditorFontSizeField.getText())));
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
return OptionsConstants.DEFAULT_EDITOR_FONT_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
private float getLineSpacingFromField() {
|
||||
try {
|
||||
return Math.min(30, Math.max(1, Float.parseFloat(myLineSpacingField.getText())));
|
||||
} catch (NumberFormatException e){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private void syncFontFamilies() {
|
||||
if (myIsInSchemeChange) {
|
||||
return;
|
||||
}
|
||||
FontPreferences fontPreferences = getFontPreferences();
|
||||
fontPreferences.clearFonts();
|
||||
String primaryFontFamily = (String)myPrimaryCombo.getSelectedItem();
|
||||
String secondaryFontFamily = mySecondaryCombo.isEnabled() ? (String)mySecondaryCombo.getSelectedItem() : null;
|
||||
int fontSize = getFontSizeFromField();
|
||||
if (primaryFontFamily != null ) {
|
||||
if (!FontPreferences.DEFAULT_FONT_NAME.equals(primaryFontFamily)) {
|
||||
fontPreferences.addFontFamily(primaryFontFamily);
|
||||
}
|
||||
fontPreferences.register(primaryFontFamily, fontSize);
|
||||
}
|
||||
if (secondaryFontFamily != null) {
|
||||
if (!FontPreferences.DEFAULT_FONT_NAME.equals(secondaryFontFamily)){
|
||||
fontPreferences.addFontFamily(secondaryFontFamily);
|
||||
}
|
||||
fontPreferences.register(secondaryFontFamily, fontSize);
|
||||
}
|
||||
updateDescription(true);
|
||||
}
|
||||
|
||||
|
||||
public static void showReadOnlyMessage(JComponent parent, final boolean sharedScheme) {
|
||||
if (!sharedScheme) {
|
||||
Messages.showMessageDialog(
|
||||
@@ -262,65 +228,25 @@ public class FontOptions extends JPanel implements OptionsPanel{
|
||||
myIsInSchemeChange = true;
|
||||
|
||||
myLineSpacingField.setText(Float.toString(getLineSpacing()));
|
||||
mySelectedFontsModel.clear();
|
||||
FontPreferences fontPreferences = getFontPreferences();
|
||||
List<String> fontFamilies = fontPreferences.getEffectiveFontFamilies();
|
||||
Set<String> selectedFonts = ContainerUtilRt.newHashSet();
|
||||
Object selectedValue = mySelectedFontsList.getSelectedValue();
|
||||
mySelectedFontsModel.clear();
|
||||
if (fontFamilies.isEmpty()) {
|
||||
// Add default font.
|
||||
mySelectedFontsModel.addElement(fontPreferences.getFontFamily());
|
||||
selectedFonts.add(fontPreferences.getFontFamily());
|
||||
}
|
||||
else {
|
||||
for (String fontFamily : fontFamilies) {
|
||||
mySelectedFontsModel.addElement(fontFamily);
|
||||
selectedFonts.add(fontFamily);
|
||||
}
|
||||
}
|
||||
|
||||
int newSelectionIndex = 0;
|
||||
if (selectedValue != null) {
|
||||
newSelectionIndex = Math.max(0, mySelectedFontsModel.indexOf(selectedValue));
|
||||
}
|
||||
mySelectedFontsList.setSelectedIndex(newSelectionIndex);
|
||||
|
||||
for (int i = myAllFontsModel.size() - 1; i >= 0; i--) {
|
||||
if (selectedFonts.contains(myAllFontsModel.getElementAt(i))) {
|
||||
myAllFontsModel.remove(i);
|
||||
}
|
||||
}
|
||||
myPrimaryCombo.setSelectedItem(fontPreferences.getFontFamily());
|
||||
boolean isThereSecondaryFont = fontFamilies.size() > 1;
|
||||
myUseSecondaryFontCheckbox.setSelected(isThereSecondaryFont);
|
||||
mySecondaryCombo.setSelectedItem(isThereSecondaryFont ? fontFamilies.get(1) : null);
|
||||
myEditorFontSizeField.setText(String.valueOf(fontPreferences.getSize(fontPreferences.getFontFamily())));
|
||||
|
||||
boolean enabled = !ColorAndFontOptions.isReadOnly(myOptions.getSelectedScheme());
|
||||
myOnlyMonospacedCheckBox.setEnabled(enabled);
|
||||
myLineSpacingField.setEnabled(enabled);
|
||||
myEditorFontSizeField.setEditable(enabled);
|
||||
myFontsControl.setEnabled(enabled);
|
||||
boolean readOnly = ColorAndFontOptions.isReadOnly(myOptions.getSelectedScheme());
|
||||
myPrimaryCombo.setEnabled(!readOnly);
|
||||
mySecondaryCombo.setEnabled(isThereSecondaryFont && !readOnly);
|
||||
myOnlyMonospacedCheckBox.setEnabled(!readOnly);
|
||||
myLineSpacingField.setEnabled(!readOnly);
|
||||
myEditorFontSizeField.setEditable(!readOnly);
|
||||
myUseSecondaryFontCheckbox.setEnabled(!readOnly);
|
||||
|
||||
myIsInSchemeChange = false;
|
||||
}
|
||||
|
||||
private void onFontsInit() {
|
||||
assert myFontNames != null;
|
||||
Object selectedValue = myAllFontsList.getSelectedValue();
|
||||
myAllFontsModel.clear();
|
||||
List<String> availableFonts = myOnlyMonospacedCheckBox.isSelected() ? myMonospacedFontNames : myFontNames;
|
||||
int newSelectionIndex = 0;
|
||||
int i = 0;
|
||||
for (String name : availableFonts) {
|
||||
if (!mySelectedFontsModel.contains(name)) { // Don't bother with performance here in assumption that fallback fonts sequence is short
|
||||
myAllFontsModel.addElement(name);
|
||||
if (name.equals(selectedValue)) {
|
||||
newSelectionIndex = i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
myAllFontsList.setSelectedIndex(newSelectionIndex);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected FontPreferences getFontPreferences() {
|
||||
return getCurrentScheme().getFontPreferences();
|
||||
@@ -352,44 +278,13 @@ public class FontOptions extends JPanel implements OptionsPanel{
|
||||
return myOptions.getSelectedScheme();
|
||||
}
|
||||
|
||||
private JPanel createEditorFontPanel() {
|
||||
JPanel editorFontPanel = new JPanel(new GridBagLayout());
|
||||
Insets borderInsets = new Insets(IdeBorderFactory.TITLED_BORDER_TOP_INSET,
|
||||
IdeBorderFactory.TITLED_BORDER_LEFT_INSET,
|
||||
0,
|
||||
IdeBorderFactory.TITLED_BORDER_RIGHT_INSET);
|
||||
editorFontPanel.setBorder(IdeBorderFactory.createTitledBorder(myTitle, false, borderInsets));
|
||||
|
||||
Insets insets = new Insets(0, 0, 5, 0);
|
||||
GridBag constraints = new GridBag().insets(insets);
|
||||
editorFontPanel.add(myOnlyMonospacedCheckBox, constraints);
|
||||
|
||||
insets.left = 8;
|
||||
editorFontPanel.add(new JLabel(ApplicationBundle.message("editbox.font.size")), constraints);
|
||||
|
||||
insets.left = 2;
|
||||
editorFontPanel.add(myEditorFontSizeField, constraints);
|
||||
|
||||
insets.left = 8;
|
||||
editorFontPanel.add(new JLabel(ApplicationBundle.message("editbox.line.spacing")), constraints);
|
||||
|
||||
insets.left = 2;
|
||||
editorFontPanel.add(myLineSpacingField, constraints);
|
||||
|
||||
editorFontPanel.add(new JLabel(""), new GridBag().insets(insets).weightx(1).fillCellHorizontally().coverLine());
|
||||
|
||||
editorFontPanel.add(myFontsControl, new GridBag().weightx(1).weighty(1).fillCell().coverLine().insets(insets));
|
||||
|
||||
return editorFontPanel;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"AssignmentToStaticFieldFromInstanceMethod"})
|
||||
private void initFontTables() {
|
||||
private void initFontTables(FontNameCombo popupCallback) {
|
||||
if (myFontNames == null) {
|
||||
myFontNames = new ArrayList<String>();
|
||||
myMonospacedFontNames = new ArrayList<String>();
|
||||
|
||||
ProgressManager.getInstance().runProcessWithProgressSynchronously(new InitFontsRunnable(), ApplicationBundle.message("progress.analyzing.fonts"), false, null);
|
||||
ProgressManager.getInstance().runProcessWithProgressSynchronously(new InitFontsRunnable(popupCallback), ApplicationBundle.message("progress.analyzing.fonts"), false, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,18 +316,13 @@ public class FontOptions extends JPanel implements OptionsPanel{
|
||||
return new HashSet<String>();
|
||||
}
|
||||
|
||||
private static class MyTextField extends JTextField {
|
||||
private MyTextField(int size) {
|
||||
super(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumSize() {
|
||||
return getPreferredSize();
|
||||
}
|
||||
}
|
||||
|
||||
private class InitFontsRunnable implements Runnable {
|
||||
private final FontNameCombo myPopupCallback;
|
||||
|
||||
private InitFontsRunnable(FontNameCombo popupCallback) {
|
||||
myPopupCallback = popupCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
|
||||
@@ -482,9 +372,93 @@ public class FontOptions extends JPanel implements OptionsPanel{
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onFontsInit();
|
||||
myPrimaryCombo.updateModel();
|
||||
mySecondaryCombo.updateModel();
|
||||
myPopupCallback.showPopup();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private class FontNameCombo extends JComboBox {
|
||||
private final DefaultComboBoxModel myModel;
|
||||
private Boolean myMonospacedOnly = null;
|
||||
|
||||
private FontNameCombo(String selectedName) {
|
||||
setModel(myModel = new DefaultComboBoxModel());
|
||||
updateModel();
|
||||
setSelectedItem(selectedName);
|
||||
}
|
||||
|
||||
private void updateModel() {
|
||||
if (myFontNames == null || myMonospacedFontNames == null) return;
|
||||
|
||||
if (myMonospacedOnly == null || myMonospacedOnly.booleanValue() != EditorColorsManager.getInstance().isUseOnlyMonospacedFonts()) {
|
||||
myMonospacedOnly = EditorColorsManager.getInstance().isUseOnlyMonospacedFonts();
|
||||
|
||||
Object tmp = getSelectedItem();
|
||||
myModel.removeAllElements();
|
||||
List toAdd = myMonospacedOnly ? myMonospacedFontNames : myFontNames;
|
||||
for (Object o : toAdd) {
|
||||
myModel.addElement(o);
|
||||
}
|
||||
if (myModel.getIndexOf(tmp) != -1) {
|
||||
setSelectedItem(tmp);
|
||||
} else {
|
||||
setSelectedItem(FontPreferences.DEFAULT_FONT_NAME);
|
||||
}
|
||||
|
||||
fireActionEvent();
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectedItem(Object anObject) {
|
||||
if (myModel.getSize() == 0 && anObject != null) {
|
||||
myModel.addElement(anObject);
|
||||
}
|
||||
super.setSelectedItem(anObject);
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private JList getPopupList() {
|
||||
ComboPopup popup = ReflectionUtil.getField(getUI().getClass(), getUI(), ComboPopup.class, "popup");
|
||||
return (popup != null) ? popup.getList() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void firePopupMenuWillBecomeVisible() {
|
||||
super.firePopupMenuWillBecomeVisible();
|
||||
if (myFontNames == null) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
initFontTables(FontNameCombo.this);
|
||||
}
|
||||
});
|
||||
}
|
||||
final JList list = getPopupList();
|
||||
if (list != null && !(list.getCellRenderer() instanceof MyListCellRenderer)) {
|
||||
list.setCellRenderer(new MyListCellRenderer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyListCellRenderer extends DefaultListCellRenderer {
|
||||
public Component getListCellRendererComponent(
|
||||
JList list,
|
||||
Object value,
|
||||
int index,
|
||||
boolean isSelected,
|
||||
boolean cellHasFocus) {
|
||||
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
if (value instanceof String) {
|
||||
c.setFont(new Font((String) value, Font.PLAIN, 14));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-2
@@ -32,23 +32,31 @@ public class CapitalizeAndUnderscoreMacro extends MacroBase {
|
||||
super("capitalizeAndUnderscore", CodeInsightBundle.message("macro.capitalizeAndUnderscore.string"));
|
||||
}
|
||||
|
||||
protected CapitalizeAndUnderscoreMacro(String name, String description) {
|
||||
super(name, description);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result calculateResult(@NotNull Expression[] params, ExpressionContext context, boolean quick) {
|
||||
String text = getTextResult(params, context, true);
|
||||
if (text != null && text.length() > 0) {
|
||||
final String[] words = NameUtil.nameToWords(text);
|
||||
boolean insertUnderscore = false;
|
||||
final StringBuffer buf = new StringBuffer();
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
for (String word : words) {
|
||||
if (insertUnderscore) {
|
||||
buf.append("_");
|
||||
} else {
|
||||
insertUnderscore = true;
|
||||
}
|
||||
buf.append(StringUtil.toUpperCase(word));
|
||||
buf.append(convertCase(word));
|
||||
}
|
||||
return new TextResult(buf.toString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String convertCase(String word) {
|
||||
return StringUtil.toUpperCase(word);
|
||||
}
|
||||
}
|
||||
|
||||
+8
-14
@@ -13,24 +13,18 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.refactoring.introduce.constant;
|
||||
|
||||
import com.intellij.ui.components.JBCheckBox;
|
||||
|
||||
import javax.swing.*;
|
||||
package com.intellij.codeInsight.template.macro;
|
||||
|
||||
/**
|
||||
* Created by Max Medvedev on 8/29/13
|
||||
* @author yole
|
||||
*/
|
||||
public class GrInplaceIntroduceConstantPanel {
|
||||
private JBCheckBox myMoveToAnotherClassJBCheckBox;
|
||||
private JPanel myRootPane;
|
||||
|
||||
public boolean isMoveToAnotherClass() {
|
||||
return myMoveToAnotherClassJBCheckBox.isSelected();
|
||||
public class SnakeCaseMacro extends CapitalizeAndUnderscoreMacro {
|
||||
public SnakeCaseMacro() {
|
||||
super("snakeCase", "snakeCase(String)");
|
||||
}
|
||||
|
||||
public JComponent getRootPane() {
|
||||
return myRootPane;
|
||||
@Override
|
||||
protected String convertCase(String word) {
|
||||
return word.toLowerCase();
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,7 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.actions.TextComponentEditorAction;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.openapi.fileEditor.impl.EditorHistoryManager;
|
||||
import com.intellij.openapi.keymap.KeymapManager;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.openapi.keymap.MacKeymapUtil;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
@@ -217,8 +218,10 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
|
||||
private void run(KeyEvent event) {
|
||||
final ActionManager actionManager = ActionManager.getInstance();
|
||||
final AnAction action = actionManager.getAction("SearchEverywhere");
|
||||
|
||||
final AnAction action = actionManager.getAction(IdeActions.ACTION_SEARCH_EVERYWHERE);
|
||||
if (KeymapManager.getInstance().getActiveKeymap().getShortcuts(IdeActions.ACTION_SEARCH_EVERYWHERE).length > 0) {
|
||||
return;
|
||||
}
|
||||
final AnActionEvent anActionEvent = new AnActionEvent(event,
|
||||
DataManager.getInstance().getDataContext(IdeFocusManager.findInstance().getFocusOwner()),
|
||||
ActionPlaces.UNKNOWN,
|
||||
@@ -314,10 +317,17 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
}
|
||||
|
||||
private void initTooltip(JLabel label) {
|
||||
label.setToolTipText("<html><body>Search Everywhere<br/>Press <b>" +
|
||||
"Double " +
|
||||
(SystemInfo.isMac ? MacKeymapUtil.SHIFT : "Shift") +
|
||||
"</b> to access<br/> - Classes<br/> - Files<br/> - Tool Windows<br/> - Actions<br/> - Settings</body></html>");
|
||||
final Shortcut[] shortcuts = KeymapManager.getInstance().getActiveKeymap().getShortcuts(IdeActions.ACTION_SEARCH_EVERYWHERE);
|
||||
final String shortcutText;
|
||||
if (shortcuts.length == 0) {
|
||||
shortcutText = "Double " + (SystemInfo.isMac ? MacKeymapUtil.SHIFT : "Shift");
|
||||
} else {
|
||||
shortcutText = KeymapUtil.getShortcutsText(shortcuts);
|
||||
}
|
||||
|
||||
label.setToolTipText("<html><body>Search Everywhere<br/>Press <b>"
|
||||
+ shortcutText
|
||||
+ "</b> to access<br/> - Classes<br/> - Files<br/> - Tool Windows<br/> - Actions<br/> - Settings</body></html>");
|
||||
|
||||
}
|
||||
|
||||
@@ -589,7 +599,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
initSearchActions(myBalloon, myPopupField);
|
||||
IdeFocusManager focusManager = IdeFocusManager.getInstance(e.getProject());
|
||||
focusManager.requestFocus(myPopupField.getTextEditor(), true);
|
||||
// FeatureUsageTracker.getInstance().triggerFeatureUsed("SearchEverywhere");
|
||||
// FeatureUsageTracker.getInstance().triggerFeatureUsed(IdeActions.ACTION_SEARCH_EVERYWHERE);
|
||||
}
|
||||
|
||||
private void initSearchActions(JBPopup balloon, MySearchTextField searchTextField) {
|
||||
|
||||
+7
-7
@@ -181,7 +181,7 @@ public class CodeStyleManagerImpl extends CodeStyleManager {
|
||||
// So, if 'virtual space in editor' is enabled, we save target visual column. Caret indent is ensured otherwise
|
||||
int visualColumnToRestore = -1;
|
||||
String caretIndentToRestore = null;
|
||||
RangeMarker caretRangeMarker = null;
|
||||
RangeMarker beforeCaretRangeMarker = null;
|
||||
|
||||
if (editor != null) {
|
||||
Document document = editor.getDocument();
|
||||
@@ -202,7 +202,7 @@ public class CodeStyleManagerImpl extends CodeStyleManager {
|
||||
if (fixCaretPosition) {
|
||||
visualColumnToRestore = editor.getCaretModel().getVisualPosition().column;
|
||||
caretIndentToRestore = document.getText(TextRange.create(lineStartOffset, caretOffset));
|
||||
caretRangeMarker = document.createRangeMarker(lineStartOffset, caretOffset);
|
||||
beforeCaretRangeMarker = document.createRangeMarker(0, lineStartOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,11 +261,11 @@ public class CodeStyleManagerImpl extends CodeStyleManager {
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (caretRangeMarker == null || !caretRangeMarker.isValid() || caretIndentToRestore == null) {
|
||||
if (beforeCaretRangeMarker == null || !beforeCaretRangeMarker.isValid() || caretIndentToRestore == null) {
|
||||
return;
|
||||
}
|
||||
int offset = caretRangeMarker.getStartOffset();
|
||||
caretRangeMarker.dispose();
|
||||
int offset = beforeCaretRangeMarker.getEndOffset();
|
||||
beforeCaretRangeMarker.dispose();
|
||||
if (editor.getCaretModel().getVisualPosition().column == visualColumnToRestore) {
|
||||
return;
|
||||
}
|
||||
@@ -484,10 +484,10 @@ public class CodeStyleManagerImpl extends CodeStyleManager {
|
||||
* </ol>
|
||||
* </pre>
|
||||
* <p/>
|
||||
* This method inserts that dummy comment (fallback to identifier <code>xxx</code>, see {@link CodeStyleManagerImpl#createDummy(PsiFile)})
|
||||
* This method inserts that dummy comment (fallback to identifier <code>xxx</code>, see {@link CodeStyleManagerImpl#createDummy(PsiFile)})
|
||||
* if necessary (if target line contains white space symbols only).
|
||||
* <p/>
|
||||
|
||||
|
||||
* <b>Note:</b> it's expected that the whole white space region that contains given offset is processed in a way that all
|
||||
* {@link RangeMarker range markers} registered for the given offset are expanded to the whole white space region.
|
||||
* E.g. there is a possible case that particular range marker serves for defining formatting range, hence, its start/end offsets
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -44,7 +44,7 @@ import java.util.List;
|
||||
// This prevents languages with polyadic expressions or sequences
|
||||
// from reusing it, use simpleChooser instead.
|
||||
public abstract class OccurrencesChooser<T> {
|
||||
public static enum ReplaceChoice {
|
||||
public enum ReplaceChoice {
|
||||
NO("Replace this occurrence only"), NO_WRITE("Replace all occurrences but write"), ALL("Replace all {0} occurrences");
|
||||
|
||||
private final String myDescription;
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,6 +30,7 @@ import com.intellij.lang.refactoring.NamesValidator;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.Shortcut;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.command.impl.FinishMarkAction;
|
||||
@@ -327,7 +328,7 @@ public abstract class InplaceRefactoring {
|
||||
|
||||
new WriteCommandAction(myProject, getCommandName()) {
|
||||
@Override
|
||||
protected void run(com.intellij.openapi.application.Result result) throws Throwable {
|
||||
protected void run(Result result) throws Throwable {
|
||||
startTemplate(builder);
|
||||
}
|
||||
}.execute();
|
||||
|
||||
@@ -44,21 +44,12 @@ public class EditorTextFieldActionPromoter implements ActionPromoter {
|
||||
private static final Comparator<AnAction> ACTIONS_COMPARATOR = new Comparator<AnAction>() {
|
||||
@Override
|
||||
public int compare(AnAction o1, AnAction o2) {
|
||||
if (o1 instanceof EditorAction && o2 instanceof EditorAction) {
|
||||
return 0;
|
||||
}
|
||||
if (o1 instanceof TextComponentEditorAction) {
|
||||
return -1;
|
||||
}
|
||||
if (o2 instanceof TextComponentEditorAction) {
|
||||
return 1;
|
||||
}
|
||||
if (o1 instanceof EditorAction) {
|
||||
return 1;
|
||||
}
|
||||
if (o2 instanceof EditorAction) {
|
||||
return -1;
|
||||
}
|
||||
boolean textFieldAction1 = o1 instanceof TextComponentEditorAction;
|
||||
boolean textFieldAction2 = o2 instanceof TextComponentEditorAction;
|
||||
boolean plainEditorAction1 = o1 instanceof EditorAction && !textFieldAction1;
|
||||
boolean plainEditorAction2 = o2 instanceof EditorAction && !textFieldAction2;
|
||||
if (textFieldAction1 && plainEditorAction2) return -1;
|
||||
if (textFieldAction2 && plainEditorAction1) return 1;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -267,4 +267,5 @@ public interface IdeActions {
|
||||
String MOVE_TO_ANOTHER_CHANGE_LIST = "ChangesView.Move";
|
||||
|
||||
String ACTION_RECENT_FILES = "RecentFiles";
|
||||
String ACTION_SEARCH_EVERYWHERE = "SearchEverywhere";
|
||||
}
|
||||
|
||||
+15
-17
@@ -37,7 +37,6 @@ import com.intellij.openapi.util.ActionCallback;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.IdRunnable;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.openapi.wm.ex.WindowManagerEx;
|
||||
@@ -80,9 +79,9 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
|
||||
/**
|
||||
* This array contains Rectangles which define bounds of the corresponding
|
||||
* components in the toolbar. This list can be considerer as a cache of the
|
||||
* components in the toolbar. This list can be consider as a cache of the
|
||||
* Rectangle objects that are used in calculation of preferred sizes and
|
||||
* layouting of components.
|
||||
* components layout.
|
||||
*/
|
||||
private final List<Rectangle> myComponentBounds = new ArrayList<Rectangle>();
|
||||
|
||||
@@ -123,7 +122,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
private ActionButton mySecondaryActionsButton;
|
||||
private final KeymapManagerEx myKeymapManager;
|
||||
|
||||
private int myFirstOusideIndex = -1;
|
||||
private int myFirstOutsideIndex = -1;
|
||||
private JBPopup myPopup;
|
||||
|
||||
private JComponent myTargetComponent;
|
||||
@@ -183,7 +182,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
myTimerListener = new MyTimerListener();
|
||||
myWeakTimerListener = new WeakTimerListener(actionManager, myTimerListener);
|
||||
// If the panel doesn't handle mouse event then it will be passed to its parent.
|
||||
// It means that if the panel is in slidindg mode then the focus goes to the editor
|
||||
// It means that if the panel is in sliding mode then the focus goes to the editor
|
||||
// and panel will be automatically hidden.
|
||||
enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK | AWTEvent.COMPONENT_EVENT_MASK | AWTEvent.CONTAINER_EVENT_MASK);
|
||||
setMiniMode(false);
|
||||
@@ -300,7 +299,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
add(mySecondaryActionsButton);
|
||||
}
|
||||
|
||||
if (Registry.is("search.everywhere.enabled") && (ActionPlaces.MAIN_TOOLBAR.equals(myPlace) || ActionPlaces.NAVIGATION_BAR.equals(myPlace))) {
|
||||
if ((ActionPlaces.MAIN_TOOLBAR.equals(myPlace) || ActionPlaces.NAVIGATION_BAR.equals(myPlace))) {
|
||||
final AnAction searchEverywhereAction = ActionManager.getInstance().getAction("SearchEverywhere");
|
||||
if (searchEverywhereAction != null) {
|
||||
try {
|
||||
@@ -520,7 +519,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
if (full) {
|
||||
if (myAutoPopupRec == null) {
|
||||
myAutoPopupRec = new Rectangle(eachX, eachY, sizeToFit.width - eachX - 1, sizeToFit.height - 1);
|
||||
myFirstOusideIndex = i;
|
||||
myFirstOutsideIndex = i;
|
||||
}
|
||||
eachBound.x = Integer.MAX_VALUE;
|
||||
eachBound.y = Integer.MAX_VALUE;
|
||||
@@ -562,7 +561,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
if (full) {
|
||||
if (myAutoPopupRec == null) {
|
||||
myAutoPopupRec = new Rectangle(eachX, eachY, sizeToFit.width - 1, sizeToFit.height - eachY - 1);
|
||||
myFirstOusideIndex = i;
|
||||
myFirstOutsideIndex = i;
|
||||
}
|
||||
eachBound.x = Integer.MAX_VALUE;
|
||||
eachBound.y = Integer.MAX_VALUE;
|
||||
@@ -575,7 +574,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
}
|
||||
|
||||
private void calculateBoundsWrapImpl(Dimension sizeToFit, List<Rectangle> bounds) {
|
||||
// We have to gracefull handle case when toolbar was not layed out yet.
|
||||
// We have to graceful handle case when toolbar was not laid out yet.
|
||||
// In this case we calculate bounds as it is a NOWRAP toolbar.
|
||||
if (getWidth() == 0 || getHeight() == 0) {
|
||||
try {
|
||||
@@ -611,7 +610,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
}
|
||||
|
||||
final Rectangle each = bounds.get(i);
|
||||
each.setBounds(xOffset, maxWidth, yOffset, maxHeight);
|
||||
each.setBounds(xOffset, yOffset, maxWidth, maxHeight);
|
||||
|
||||
xOffset += maxWidth;
|
||||
}
|
||||
@@ -632,7 +631,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
}
|
||||
|
||||
final Rectangle each = bounds.get(i);
|
||||
each.setBounds(xOffset, maxWidth, yOffset, maxHeight);
|
||||
each.setBounds(xOffset, yOffset, maxWidth, maxHeight);
|
||||
|
||||
yOffset += maxHeight;
|
||||
}
|
||||
@@ -642,7 +641,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
if (myOrientation == SwingConstants.HORIZONTAL) {
|
||||
// Calculate row height
|
||||
int rowHeight = 0;
|
||||
final Dimension[] dims = new Dimension[componentCount]; // we will use this dimesions later
|
||||
final Dimension[] dims = new Dimension[componentCount]; // we will use this dimensions later
|
||||
for (int i = 0; i < componentCount; i++) {
|
||||
dims[i] = getChildPreferredSize(i);
|
||||
final int height = dims[i].height;
|
||||
@@ -670,7 +669,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
else {
|
||||
// Calculate row width
|
||||
int rowWidth = 0;
|
||||
final Dimension[] dims = new Dimension[componentCount]; // we will use this dimesions later
|
||||
final Dimension[] dims = new Dimension[componentCount]; // we will use this dimensions later
|
||||
for (int i = 0; i < componentCount; i++) {
|
||||
dims[i] = getChildPreferredSize(i);
|
||||
final int width = dims[i].width;
|
||||
@@ -717,13 +716,12 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
calculateBoundsAutoImp(size2Fit, bounds);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("unknonw layoutPolicy: " + myLayoutPolicy);
|
||||
throw new IllegalStateException("unknown layoutPolicy: " + myLayoutPolicy);
|
||||
}
|
||||
|
||||
if (getComponentCount() > 0 && size2Fit.width < Integer.MAX_VALUE) {
|
||||
final Component component = getComponent(getComponentCount() - 1);
|
||||
if (component instanceof JComponent && ((JComponent)component).getClientProperty("SEARCH_EVERYWHERE") == Boolean.TRUE) {
|
||||
final Rectangle rect = bounds.get(bounds.size() - 1);
|
||||
int max = 0;
|
||||
for (int i = 0; i < bounds.size() - 2; i++) {
|
||||
max = Math.max(max, bounds.get(i).height);
|
||||
@@ -799,7 +797,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
final Insets i = getInsets();
|
||||
if (UIUtil.isUnderAquaBasedLookAndFeel() || UIUtil.isUnderDarcula()) {
|
||||
if (getParent() != null) {
|
||||
final JBColor col = new JBColor(Color.GRAY, Gray._111);
|
||||
final JBColor col = new JBColor(Gray._128, Gray._111);
|
||||
final Graphics2D g2 = (Graphics2D)g;
|
||||
if (myOrientation == SwingConstants.HORIZONTAL) {
|
||||
UIUtil.drawDoubleSpaceDottedLine(g2, i.top + 2, getParent().getSize().height - 2 - i.top - i.bottom, 3, col, false);
|
||||
@@ -1029,7 +1027,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
|
||||
}
|
||||
else {
|
||||
final DefaultActionGroup outside = new DefaultActionGroup();
|
||||
for (int i = myFirstOusideIndex; i < myVisibleActions.size(); i++) {
|
||||
for (int i = myFirstOutsideIndex; i < myVisibleActions.size(); i++) {
|
||||
outside.add(myVisibleActions.get(i));
|
||||
}
|
||||
group = outside;
|
||||
|
||||
@@ -64,7 +64,8 @@ public class LocalFsFinder implements FileLookup.Finder, FileLookup {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String normalize(@NotNull final String path) {
|
||||
public String normalize(@NotNull String path) {
|
||||
path = FileUtil.expandUserHome(path);
|
||||
final File file = new File(path);
|
||||
if (file.isAbsolute()) return file.getAbsolutePath();
|
||||
|
||||
|
||||
+7
-4
@@ -31,7 +31,6 @@ import com.intellij.openapi.keymap.MacKeymapUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Splitter;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.*;
|
||||
@@ -170,10 +169,14 @@ public class EditorsSplitters extends IdePanePanel {
|
||||
|
||||
painter.appendLine("No files are open").underlined(new JBColor(isDarkBackground ? Gray._210 : Gray._150, Gray._100));
|
||||
|
||||
if (Registry.is("search.everywhere.enabled")) {
|
||||
painter.appendLine("Search Everywhere with Double " + (SystemInfo.isMac ? MacKeymapUtil.SHIFT : "Shift"))
|
||||
.smaller().withBullet();
|
||||
final Shortcut[] shortcuts = KeymapManager.getInstance().getActiveKeymap().getShortcuts(IdeActions.ACTION_SEARCH_EVERYWHERE);
|
||||
final String everywhere;
|
||||
if (shortcuts.length == 0) {
|
||||
everywhere = "Search Everywhere with Double " + (SystemInfo.isMac ? MacKeymapUtil.SHIFT : "Shift");
|
||||
} else {
|
||||
everywhere = "Search Everywhere " + KeymapUtil.getShortcutsText(shortcuts);
|
||||
}
|
||||
painter.appendLine(everywhere).smaller().withBullet();
|
||||
|
||||
if (!isProjectViewVisible()) {
|
||||
painter.appendLine("Open Project View with " + KeymapUtil.getShortcutText(new KeyboardShortcut(
|
||||
|
||||
@@ -475,6 +475,8 @@ error.illegal.scheme.name=Illegal scheme name
|
||||
error.a.scheme.with.this.name.already.exists.or.was.deleted.without.applying.the.changes=A scheme with this name already exists or was deleted without applying the changes
|
||||
title.select.font=Select Font
|
||||
checkbox.show.only.monospaced.fonts=Show only monospaced fonts
|
||||
primary.font=Primary font:
|
||||
secondary.font=Secondary font:
|
||||
editbox.enter.tag.name=Enter tag name:
|
||||
title.tag.name=Tag Name
|
||||
title.xml=XML
|
||||
@@ -503,9 +505,7 @@ title.colors.and.fonts=Colors \\& Fonts
|
||||
progress.analysing.font=Analysing font: {0}
|
||||
button.edit.scopes=Edit Scopes...
|
||||
group.editor.font=Editor Font
|
||||
title.font.available=Available fonts:
|
||||
title.font.selected=Selected fonts:
|
||||
label.fallback.fonts.list.description=The ide tries to use the next font from 'Selected fonts' list for displaying a symbol if the current font fails to do that
|
||||
label.fallback.fonts.list.description=If primary font fails IDE tries to use the secondary one
|
||||
quickdoc.tooltip.font.size.by.wheel=Slider or Ctrl+Wheel change font size
|
||||
label.font.size=Font size:
|
||||
label.font.name=Name:
|
||||
|
||||
@@ -298,7 +298,6 @@ enable.graph.inference=false
|
||||
comment.by.line.bulk.lines.trigger=100
|
||||
|
||||
scene.builder.start.executable=true
|
||||
search.everywhere.enabled=true
|
||||
junit_sm_runner=false
|
||||
testng_sm_runner=false
|
||||
show.flex.debug.design.view=false
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
<liveTemplateMacro implementation="com.intellij.codeInsight.template.macro.FileNameWithoutExtensionMacro"/>
|
||||
<liveTemplateMacro implementation="com.intellij.codeInsight.template.macro.ReplaceUnderscoresToCamelCaseMacro"/>
|
||||
<liveTemplateMacro implementation="com.intellij.codeInsight.template.macro.CapitalizeAndUnderscoreMacro"/>
|
||||
<liveTemplateMacro implementation="com.intellij.codeInsight.template.macro.SnakeCaseMacro"/>
|
||||
|
||||
<liveTemplateMacro implementation="com.intellij.codeInsight.template.macro.CompleteMacro"/>
|
||||
<liveTemplateMacro implementation="com.intellij.codeInsight.template.macro.CompleteSmartMacro"/>
|
||||
@@ -663,7 +664,7 @@
|
||||
|
||||
<!-- HighlightManagerActions -->
|
||||
<editorActionHandler action="EditorEscape" implementationClass="com.intellij.codeInsight.highlighting.EscapeHandler"
|
||||
order="after hide-hints"/>
|
||||
order="after hide-hints" id="hide-search"/>
|
||||
<editorActionHandler action="EditorEscape" implementationClass="com.intellij.refactoring.rename.inplace.EscapeHandler"
|
||||
order="before hide-hints"/>
|
||||
|
||||
|
||||
@@ -129,7 +129,8 @@ public class PathMacrosImpl extends PathMacros implements ApplicationComponent,
|
||||
"SelectionStartLine",
|
||||
"SelectionEndLine",
|
||||
"SelectionStartColumn",
|
||||
"SelectionEndColumn"
|
||||
"SelectionEndColumn",
|
||||
"PyInterpreterDirectory"
|
||||
);
|
||||
|
||||
public PathMacrosImpl() {
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.plugins.gradle.codeInsight;
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionContributor;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCommandArgumentList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.literals.GrLiteralImpl;
|
||||
|
||||
import static com.intellij.patterns.PlatformPatterns.psiElement;
|
||||
import static com.intellij.patterns.PlatformPatterns.psiFile;
|
||||
import static com.intellij.patterns.StandardPatterns.string;
|
||||
|
||||
/**
|
||||
* @author Vladislav.Soroka
|
||||
* @since 11/1/13
|
||||
*/
|
||||
public abstract class AbstractGradleCompletionContributor extends CompletionContributor {
|
||||
protected static final ElementPattern<PsiElement> GRADLE_FILE_PATTERN = psiElement()
|
||||
.inFile(psiFile().withName(string().endsWith('.' + GradleConstants.EXTENSION)));
|
||||
|
||||
@Nullable
|
||||
protected String findNamedArgumentValue(@Nullable GrCommandArgumentList argumentList, @NotNull String label) {
|
||||
if (argumentList == null) return null;
|
||||
GrNamedArgument namedArgument = argumentList.findNamedArgument(label);
|
||||
if (namedArgument == null) return null;
|
||||
|
||||
GrExpression expression = namedArgument.getExpression();
|
||||
if (!(expression instanceof GrLiteralImpl)) return null;
|
||||
Object value = GrLiteralImpl.class.cast(expression).getValue();
|
||||
return value == null ? null : String.valueOf(value);
|
||||
}
|
||||
}
|
||||
+17
-24
@@ -22,19 +22,20 @@ import com.intellij.icons.AllIcons;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
import com.intellij.patterns.PatternCondition;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.maven.indices.MavenArtifactSearchResult;
|
||||
import org.jetbrains.idea.maven.indices.MavenArtifactSearcher;
|
||||
import org.jetbrains.idea.maven.indices.MavenProjectIndicesManager;
|
||||
import org.jetbrains.idea.maven.model.MavenArtifactInfo;
|
||||
import org.jetbrains.idea.maven.model.MavenId;
|
||||
import org.jetbrains.plugins.gradle.codeInsight.AbstractGradleCompletionContributor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCommandArgumentList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.literals.GrLiteralImpl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -44,27 +45,31 @@ import static com.intellij.patterns.PlatformPatterns.psiElement;
|
||||
* @author Vladislav.Soroka
|
||||
* @since 10/31/13
|
||||
*/
|
||||
public class MavenDependenciesGradleCompletionContributor extends CompletionContributor {
|
||||
public class MavenDependenciesGradleCompletionContributor extends AbstractGradleCompletionContributor {
|
||||
private static final String GROUP_LABEL = "group";
|
||||
private static final String NAME_LABEL = "name";
|
||||
private static final String VERSION_LABEL = "version";
|
||||
|
||||
private static final PatternCondition<GrMethodCallExpression> EXPRESSION_PATTERN_CONDITION =
|
||||
new PatternCondition<GrMethodCallExpression>("withInvokedExpressionText") {
|
||||
private static final ElementPattern<PsiElement> DEPENDENCIES_CALL_PATTERN = psiElement()
|
||||
.inside(true, psiElement(GrMethodCallExpression.class).with(new PatternCondition<GrMethodCallExpression>("withInvokedExpressionText") {
|
||||
@Override
|
||||
public boolean accepts(@NotNull GrMethodCallExpression expression, ProcessingContext context) {
|
||||
GrExpression grExpression = expression.getInvokedExpression();
|
||||
return grExpression != null && "dependencies".equals(grExpression.getText());
|
||||
}
|
||||
};
|
||||
}));
|
||||
|
||||
private static final ElementPattern<PsiElement>
|
||||
IN_BASIC_DEPENDENCY_NOTATION = psiElement().withSuperParent(
|
||||
5, psiElement(GrMethodCallExpression.class).with(EXPRESSION_PATTERN_CONDITION));
|
||||
private static final ElementPattern<PsiElement> IN_BASIC_DEPENDENCY_NOTATION = psiElement()
|
||||
.and(GRADLE_FILE_PATTERN)
|
||||
.withParent(GrLiteral.class)
|
||||
.withSuperParent(2, psiElement(GrCommandArgumentList.class))
|
||||
.and(DEPENDENCIES_CALL_PATTERN);
|
||||
|
||||
private static final ElementPattern<PsiElement>
|
||||
IN_MAP_DEPENDENCY_NOTATION = psiElement().withSuperParent(
|
||||
6, psiElement(GrMethodCallExpression.class).with(EXPRESSION_PATTERN_CONDITION));
|
||||
private static final ElementPattern<PsiElement> IN_MAP_DEPENDENCY_NOTATION = psiElement()
|
||||
.and(GRADLE_FILE_PATTERN)
|
||||
.withParent(GrLiteral.class)
|
||||
.withSuperParent(2, psiElement(GrNamedArgument.class))
|
||||
.and(DEPENDENCIES_CALL_PATTERN);
|
||||
|
||||
|
||||
public MavenDependenciesGradleCompletionContributor() {
|
||||
@@ -144,16 +149,4 @@ public class MavenDependenciesGradleCompletionContributor extends CompletionCont
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String findNamedArgumentValue(@Nullable GrCommandArgumentList argumentList, @NotNull String label) {
|
||||
if (argumentList == null) return null;
|
||||
GrNamedArgument namedArgument = argumentList.findNamedArgument(label);
|
||||
if (namedArgument == null) return null;
|
||||
|
||||
GrExpression expression = namedArgument.getExpression();
|
||||
if (!(expression instanceof GrLiteralImpl)) return null;
|
||||
Object value = GrLiteralImpl.class.cast(expression).getValue();
|
||||
return value == null ? null : String.valueOf(value);
|
||||
}
|
||||
}
|
||||
|
||||
-11
@@ -25,18 +25,12 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/14/13 12:58 PM
|
||||
*/
|
||||
public class GradleDependenciesContributor implements GradleMethodContextContributor {
|
||||
private final static Set<String> BUILD_SCRIPT_BLOCKS = ContainerUtil.newHashSet(
|
||||
"subprojects",
|
||||
"allprojects",
|
||||
"buildscript"
|
||||
);
|
||||
|
||||
@Override
|
||||
public void process(@NotNull List<String> methodCallInfo,
|
||||
@@ -48,11 +42,6 @@ public class GradleDependenciesContributor implements GradleMethodContextContrib
|
||||
String methodCall = ContainerUtil.getLastItem(methodCallInfo);
|
||||
if (methodCall == null) return;
|
||||
|
||||
if (methodCallInfo.size() > 1 && BUILD_SCRIPT_BLOCKS.contains(methodCall)) {
|
||||
methodCallInfo.remove(methodCallInfo.size() - 1);
|
||||
methodCall = ContainerUtil.getLastItem(methodCallInfo);
|
||||
}
|
||||
|
||||
if (!StringUtil.equals(methodCall, "dependencies")) return;
|
||||
|
||||
final GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject());
|
||||
|
||||
+20
-8
@@ -155,19 +155,19 @@ public class GradleResolverUtil {
|
||||
int argsCount = getGrMethodArumentsCount(args);
|
||||
argsCount++; // Configuration name is delivered as an argument.
|
||||
|
||||
for (PsiMethod method : handlerClass.findMethodsByName(methodName, false)) {
|
||||
if (method.getParameterList().getParametersCount() == argsCount) {
|
||||
// handle setter's shortcut facilities
|
||||
final String setter = GroovyPropertyUtils.getSetterName(methodName);
|
||||
for (PsiMethod method : handlerClass.findMethodsByName(setter, false)) {
|
||||
if (method.getParameterList().getParametersCount() == 1) {
|
||||
builder.setNavigationElement(method);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// handle setter's shortcut facilities
|
||||
final String setter = GroovyPropertyUtils.getSetterName(methodName);
|
||||
for (PsiMethod method : handlerClass.findMethodsByName(setter, false)) {
|
||||
if (method.getParameterList().getParametersCount() == 1) {
|
||||
builder.setNavigationElement(method);
|
||||
return;
|
||||
for (PsiMethod method : handlerClass.findMethodsByName(methodName, false)) {
|
||||
if (method.getParameterList().getParametersCount() == argsCount) {
|
||||
builder.setNavigationElement(method);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,10 +186,22 @@ public class GradleResolverUtil {
|
||||
@NotNull ResolveState state,
|
||||
@NotNull PsiElement place,
|
||||
@NotNull String... fqNames) {
|
||||
processDeclarations(null, psiManager, processor, state, place, fqNames);
|
||||
}
|
||||
|
||||
public static void processDeclarations(@Nullable String methodName,
|
||||
@NotNull GroovyPsiManager psiManager,
|
||||
@NotNull PsiScopeProcessor processor,
|
||||
@NotNull ResolveState state,
|
||||
@NotNull PsiElement place,
|
||||
@NotNull String... fqNames) {
|
||||
for (String fqName : fqNames) {
|
||||
PsiClass psiClass = psiManager.findClassWithCache(fqName, place.getResolveScope());
|
||||
if (psiClass != null) {
|
||||
psiClass.processDeclarations(processor, state, null, place);
|
||||
if (methodName != null) {
|
||||
processMethod(methodName, psiClass, processor, state, place);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -68,6 +68,8 @@ public class GradleRootContributor implements GradleMethodContextContributor {
|
||||
}
|
||||
|
||||
GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject());
|
||||
GradleResolverUtil.processDeclarations(psiManager, processor, state, place, GradleCommonClassNames.GRADLE_API_PROJECT);
|
||||
GradleResolverUtil.processDeclarations(methodCallInfo.size() > 0 ? methodCallInfo.get(0) : null,
|
||||
psiManager, processor, state, place,
|
||||
GradleCommonClassNames.GRADLE_API_PROJECT);
|
||||
}
|
||||
}
|
||||
|
||||
+16
@@ -18,6 +18,7 @@ package org.jetbrains.plugins.gradle.service.resolve;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants;
|
||||
@@ -27,6 +28,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersContributor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
@@ -34,6 +36,15 @@ import java.util.List;
|
||||
*/
|
||||
public class GradleScriptContributor extends NonCodeMembersContributor {
|
||||
|
||||
public final static Set<String> BUILD_PROJECT_SCRIPT_BLOCKS = ContainerUtil.newHashSet(
|
||||
"project",
|
||||
"configure",
|
||||
"subprojects",
|
||||
"allprojects",
|
||||
"buildscript"
|
||||
);
|
||||
|
||||
|
||||
@Override
|
||||
public void processDynamicElements(@NotNull PsiType qualifierType,
|
||||
PsiClass aClass,
|
||||
@@ -67,6 +78,11 @@ public class GradleScriptContributor extends NonCodeMembersContributor {
|
||||
}
|
||||
}
|
||||
|
||||
final String methodCall = ContainerUtil.getLastItem(methodInfo);
|
||||
if (methodInfo.size() > 1 && BUILD_PROJECT_SCRIPT_BLOCKS.contains(methodCall)) {
|
||||
methodInfo.remove(methodInfo.size() - 1);
|
||||
}
|
||||
|
||||
for (GradleMethodContextContributor contributor : GradleMethodContextContributor.EP_NAME.getExtensions()) {
|
||||
contributor.process(methodInfo, processor, state, place);
|
||||
}
|
||||
|
||||
+4
-4
@@ -59,13 +59,13 @@ public class GradleTaskContributor implements GradleMethodContextContributor {
|
||||
processTaskAddition(methodCallInfo.get(0), GradleCommonClassNames.GRADLE_API_TASK_CONTAINER, processor, state, place);
|
||||
}
|
||||
else {
|
||||
processTaskTypeParameter(processor, state, place);
|
||||
processTaskTypeParameter(methodCallInfo.get(0), processor, state, place);
|
||||
}
|
||||
|
||||
GradleImplicitContributor.processImplicitDeclarations(processor, state, place);
|
||||
}
|
||||
else if (methodCallInfo.size() >= 3) {
|
||||
processTaskTypeParameter(processor, state, place);
|
||||
processTaskTypeParameter(methodCallInfo.get(0), processor, state, place);
|
||||
|
||||
GradleImplicitContributor.processImplicitDeclarations(processor, state, place);
|
||||
|
||||
@@ -76,7 +76,7 @@ public class GradleTaskContributor implements GradleMethodContextContributor {
|
||||
}
|
||||
}
|
||||
|
||||
private static void processTaskTypeParameter(@NotNull PsiScopeProcessor processor,
|
||||
private static void processTaskTypeParameter(@NotNull String methodCall, @NotNull PsiScopeProcessor processor,
|
||||
@NotNull ResolveState state,
|
||||
@NotNull PsiElement place) {
|
||||
final int taskTypeParameterLevel = 3;
|
||||
@@ -98,7 +98,7 @@ public class GradleTaskContributor implements GradleMethodContextContributor {
|
||||
PsiImmediateClassType immediateClassType = (PsiImmediateClassType)psiType;
|
||||
for (PsiType type : immediateClassType.getParameters()) {
|
||||
GroovyPsiManager psiManager = GroovyPsiManager.getInstance(place.getProject());
|
||||
GradleResolverUtil.processDeclarations(psiManager, processor, state, place, type.getCanonicalText());
|
||||
GradleResolverUtil.processDeclarations(methodCall, psiManager, processor, state, place, type.getCanonicalText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+277
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.refactoring.introduce;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.refactoring.introduce.inplace.AbstractInplaceIntroducer;
|
||||
import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.GroovyFileType;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Max Medvedev on 10/28/13
|
||||
*/
|
||||
public abstract class GrAbstractInplaceIntroducer<Settings extends GrIntroduceSettings> extends AbstractInplaceIntroducer<GrVariable, PsiElement> {
|
||||
|
||||
private SmartTypePointer myTypePointer;
|
||||
private OccurrencesChooser.ReplaceChoice myReplaceChoice;
|
||||
|
||||
private RangeMarker myVarMarker;
|
||||
private final PsiFile myFile;
|
||||
|
||||
private final GrIntroduceContext myContext;
|
||||
|
||||
public GrAbstractInplaceIntroducer(String title,
|
||||
OccurrencesChooser.ReplaceChoice replaceChoice,
|
||||
GrIntroduceContext context) {
|
||||
super(context.getProject(), context.getEditor(), context.getExpression(), context.getVar(), context.getOccurrences(), title, GroovyFileType.GROOVY_FILE_TYPE);
|
||||
myReplaceChoice = replaceChoice;
|
||||
myContext = context;
|
||||
myFile = context.getPlace().getContainingFile();
|
||||
}
|
||||
|
||||
public GrIntroduceContext getContext() {
|
||||
return myContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReplaceAllOccurrences(boolean allOccurrences) {
|
||||
throw new IncorrectOperationException("don't invoke this method");
|
||||
}
|
||||
|
||||
@Override
|
||||
public GrExpression restoreExpression(PsiFile containingFile, GrVariable variable, RangeMarker marker, String exprText) {
|
||||
if (exprText == null) return null;
|
||||
if (variable == null || !variable.isValid()) return null;
|
||||
final PsiElement refVariableElement = containingFile.findElementAt(marker.getStartOffset());
|
||||
final PsiElement refVariableElementParent = refVariableElement != null ? refVariableElement.getParent() : null;
|
||||
GrExpression expression =
|
||||
refVariableElementParent instanceof GrNewExpression && refVariableElement.getNode().getElementType() == GroovyTokenTypes.kNEW
|
||||
? (GrNewExpression)refVariableElementParent
|
||||
: PsiTreeUtil.getParentOfType(refVariableElement, GrReferenceExpression.class);
|
||||
if (expression instanceof GrReferenceExpression && !(expression.getParent() instanceof GrMethodCall)) {
|
||||
final String referenceName = ((GrReferenceExpression)expression).getReferenceName();
|
||||
if (((GrReferenceExpression)expression).resolve() == variable ||
|
||||
Comparing.strEqual(variable.getName(), referenceName) ||
|
||||
Comparing.strEqual(exprText, referenceName)) {
|
||||
return (GrExpression)expression
|
||||
.replace(GroovyPsiElementFactory.getInstance(myProject).createExpressionFromText(exprText, variable));
|
||||
}
|
||||
}
|
||||
if (expression == null) {
|
||||
expression = PsiTreeUtil.getParentOfType(refVariableElement, GrExpression.class);
|
||||
}
|
||||
while (expression instanceof GrReferenceExpression) {
|
||||
final PsiElement parent = expression.getParent();
|
||||
if (parent instanceof GrMethodCallExpression) {
|
||||
if (parent.getText().equals(exprText)) return (GrExpression)parent;
|
||||
}
|
||||
if (parent instanceof GrExpression) {
|
||||
expression = (GrExpression)parent;
|
||||
if (expression.getText().equals(exprText)) {
|
||||
return expression;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (expression != null && expression.isValid() && expression.getText().equals(exprText)) {
|
||||
return expression;
|
||||
}
|
||||
|
||||
if (refVariableElementParent instanceof GrExpression && refVariableElementParent.getText().equals(exprText)) {
|
||||
return (GrExpression)refVariableElementParent;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateTitle(@Nullable GrVariable variable, String value) {
|
||||
if (variable == null) {
|
||||
super.updateTitle(variable, value);
|
||||
}
|
||||
else {
|
||||
final String variableText = variable.getParent().getText();
|
||||
final PsiElement identifier = variable.getNameIdentifierGroovy();
|
||||
final int startOffsetInParent = identifier.getStartOffsetInParent() + variable.getStartOffsetInParent();
|
||||
setPreviewText(
|
||||
variableText.substring(0, startOffsetInParent) + value + variableText.substring(startOffsetInParent + identifier.getTextLength()));
|
||||
revalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateTitle(@Nullable GrVariable variable) {
|
||||
if (variable == null) return;
|
||||
setPreviewText(variable.getParent().getText());
|
||||
revalidate();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected PsiElement getNameIdentifier() {
|
||||
return ((GrVariable)myElementToRename).getNameIdentifierGroovy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GrVariable getVariable() {
|
||||
if (myVarMarker == null) return null;
|
||||
|
||||
int offset = myVarMarker.getStartOffset();
|
||||
PsiElement at = myFile.findElementAt(offset);
|
||||
GrVariable var = PsiTreeUtil.getParentOfType(at, GrVariable.class);
|
||||
return var;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performIntroduce() {
|
||||
final List<RangeMarker> markers = getOccurrenceMarkers();
|
||||
GrIntroduceContext context = new GrIntroduceContext() {
|
||||
@NotNull
|
||||
@Override
|
||||
public Project getProject() {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor getEditor() {
|
||||
return myEditor;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public GrExpression getExpression() {
|
||||
return (GrExpression)getExpr();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public GrVariable getVar() {
|
||||
return getLocalVariable();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public StringPartInfo getStringPart() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement[] getOccurrences() {
|
||||
List<PsiElement> result = ContainerUtil.map(markers, new Function<RangeMarker, PsiElement>() {
|
||||
@Override
|
||||
public PsiElement fun(RangeMarker marker) {
|
||||
return GroovyRefactoringUtil.findElementInRange(myFile, marker.getStartOffset(), marker.getEndOffset(), GrExpression.class);
|
||||
}
|
||||
});
|
||||
return PsiUtilCore.toPsiElementArray(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement getScope() {
|
||||
return myScope;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement getPlace() {
|
||||
GrExpression expression = getExpression();
|
||||
return expression != null ? expression : getLocalVariable();
|
||||
}
|
||||
};
|
||||
runRefactoring(context, getSettings(), true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected GrVariable createFieldToStartTemplateOn(boolean replaceAll, String[] names) {
|
||||
|
||||
final Settings settings = getInitialSettingsForInplace(myContext, myReplaceChoice, names);
|
||||
if (settings == null) return null;
|
||||
|
||||
SmartPsiElementPointer<GrVariable> pointer = ApplicationManager.getApplication().runWriteAction(new Computable<SmartPsiElementPointer<GrVariable>>() {
|
||||
@Override
|
||||
public SmartPsiElementPointer<GrVariable> compute() {
|
||||
GrVariable var = runRefactoring(myContext, settings, false);
|
||||
return var != null ? SmartPointerManager.getInstance(myProject).createSmartPsiElementPointer(var) : null;
|
||||
}
|
||||
});
|
||||
|
||||
if (pointer != null) {
|
||||
GrVariable var = pointer.getElement();
|
||||
if (var != null) {
|
||||
myVarMarker = myContext.getEditor().getDocument().createRangeMarker(var.getTextRange());
|
||||
}
|
||||
return var;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract GrVariable runRefactoring(GrIntroduceContext context, Settings settings, boolean processUsages);
|
||||
|
||||
@Nullable
|
||||
protected abstract Settings getInitialSettingsForInplace(@NotNull GrIntroduceContext context,
|
||||
@NotNull OccurrencesChooser.ReplaceChoice choice,
|
||||
String[] names);
|
||||
|
||||
@Override
|
||||
public boolean isReplaceAllOccurrences() {
|
||||
return myReplaceChoice != OccurrencesChooser.ReplaceChoice.NO || myContext.getOccurrences().length == 1;
|
||||
}
|
||||
|
||||
protected abstract Settings getSettings();
|
||||
|
||||
@Override
|
||||
protected void restoreState(GrVariable psiField) {
|
||||
PsiType declaredType = psiField.getDeclaredType();
|
||||
myTypePointer = declaredType != null ? SmartTypePointerManager.getInstance(myProject).createSmartTypePointer(declaredType) : null;
|
||||
super.restoreState(psiField);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected PsiType getSelectedType() {
|
||||
return myTypePointer != null ? myTypePointer.getType() : null;
|
||||
}
|
||||
}
|
||||
+31
-63
@@ -32,7 +32,6 @@ import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Pass;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
@@ -77,7 +76,7 @@ import java.util.*;
|
||||
import static org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.skipParentheses;
|
||||
|
||||
/**
|
||||
* @author Maxim.Medvedev
|
||||
* Created by Max Medvedev on 10/29/13
|
||||
*/
|
||||
public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSettings, Scope extends PsiElement> implements RefactoringActionHandler {
|
||||
private static final Logger LOG = Logger.getInstance(GrIntroduceHandlerBase.class);
|
||||
@@ -144,15 +143,8 @@ public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSetting
|
||||
@Nullable
|
||||
public abstract GrVariable runRefactoring(@NotNull GrIntroduceContext context, @NotNull Settings settings);
|
||||
|
||||
protected abstract GrInplaceIntroducer getIntroducer(@NotNull GrVariable var,
|
||||
@NotNull GrIntroduceContext context,
|
||||
@NotNull Settings settings,
|
||||
@NotNull List<RangeMarker> occurrenceMarkers,
|
||||
RangeMarker varRangeMarker,
|
||||
@Nullable RangeMarker expressionRangeMarker,
|
||||
@Nullable RangeMarker stringPartRangeMarker);
|
||||
|
||||
protected abstract Settings getSettingsForInplace(GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice);
|
||||
protected abstract GrAbstractInplaceIntroducer<Settings> getIntroducer(@NotNull GrIntroduceContext context,
|
||||
OccurrencesChooser.ReplaceChoice choice);
|
||||
|
||||
public static Map<OccurrencesChooser.ReplaceChoice, List<Object>> fillChoice(GrIntroduceContext context) {
|
||||
HashMap<OccurrencesChooser.ReplaceChoice, List<Object>> map = ContainerUtil.newLinkedHashMap();
|
||||
@@ -296,7 +288,8 @@ public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSetting
|
||||
};
|
||||
|
||||
if (scopes.length == 0) {
|
||||
CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage( getRefactoringName() + "is not available in current scope"),
|
||||
CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle
|
||||
.getCannotRefactorMessage(getRefactoringName() + "is not available in current scope"),
|
||||
getRefactoringName(), getHelpID());
|
||||
}
|
||||
else if (scopes.length == 1) {
|
||||
@@ -310,11 +303,11 @@ public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSetting
|
||||
protected abstract void showScopeChooser(Scope[] scopes, Pass<Scope> callback, Editor editor);
|
||||
|
||||
public GrIntroduceContext getContext(@NotNull Project project,
|
||||
@NotNull Editor editor,
|
||||
@Nullable GrExpression expression,
|
||||
@Nullable GrVariable variable,
|
||||
@Nullable StringPartInfo stringPart,
|
||||
@NotNull PsiElement scope) {
|
||||
@NotNull Editor editor,
|
||||
@Nullable GrExpression expression,
|
||||
@Nullable GrVariable variable,
|
||||
@Nullable StringPartInfo stringPart,
|
||||
@NotNull PsiElement scope) {
|
||||
if (variable != null) {
|
||||
final List<PsiElement> list = Collections.synchronizedList(new ArrayList<PsiElement>());
|
||||
ReferencesSearch.search(variable, new LocalSearchScope(scope)).forEach(new Processor<PsiReference>() {
|
||||
@@ -348,48 +341,6 @@ public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSetting
|
||||
checkOccurrences(context.getOccurrences());
|
||||
|
||||
|
||||
final boolean isInplace = isInplace(context.getEditor(), context.getPlace());
|
||||
Pass<OccurrencesChooser.ReplaceChoice> callback = new Pass<OccurrencesChooser.ReplaceChoice>() {
|
||||
@Override
|
||||
public void pass(final OccurrencesChooser.ReplaceChoice choice) {
|
||||
|
||||
final Settings settings = isInplace ? getSettingsForInplace(context, choice) : showDialog(context);
|
||||
if (settings == null) return;
|
||||
|
||||
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
|
||||
public void run() {
|
||||
List<RangeMarker> occurrences = ContainerUtil.newArrayList();
|
||||
Document document = editor.getDocument();
|
||||
for (PsiElement element : context.getOccurrences()) {
|
||||
occurrences.add(createRange(document, element));
|
||||
}
|
||||
RangeMarker expressionRangeMarker = createRange(document, context.getExpression());
|
||||
RangeMarker stringPartRangeMarker = createRange(document, context.getStringPart());
|
||||
RangeMarker varRangeMarker = createRange(document, context.getVar());
|
||||
|
||||
SmartPsiElementPointer<GrVariable> pointer =
|
||||
ApplicationManager.getApplication().runWriteAction(new Computable<SmartPsiElementPointer<GrVariable>>() {
|
||||
@Override
|
||||
public SmartPsiElementPointer<GrVariable> compute() {
|
||||
GrVariable var = runRefactoring(context, settings);
|
||||
return var != null
|
||||
? SmartPointerManager.getInstance(context.getProject()).createSmartPsiElementPointer(var)
|
||||
: null;
|
||||
}
|
||||
});
|
||||
GrVariable var = pointer != null ? pointer.getElement() : null;
|
||||
|
||||
if (isInplace && var != null) {
|
||||
GrInplaceIntroducer introducer = getIntroducer(var, context, settings, occurrences, varRangeMarker, expressionRangeMarker, stringPartRangeMarker);
|
||||
LinkedHashSet<String> suggestions = introducer.suggestNames(context);
|
||||
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument());
|
||||
introducer.performInplaceRefactoring(suggestions);
|
||||
}
|
||||
}
|
||||
}, getRefactoringName(), getRefactoringName());
|
||||
}
|
||||
};
|
||||
|
||||
if (isInplace(context.getEditor(), context.getPlace())) {
|
||||
Map<OccurrencesChooser.ReplaceChoice, List<Object>> occurrencesMap = fillChoice(context);
|
||||
new OccurrencesChooser<Object>(editor) {
|
||||
@@ -405,17 +356,34 @@ public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSetting
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}.showChooser(callback, occurrencesMap);
|
||||
}.showChooser(new Pass<OccurrencesChooser.ReplaceChoice>() {
|
||||
@Override
|
||||
public void pass(final OccurrencesChooser.ReplaceChoice choice) {
|
||||
getIntroducer(context, choice).startInplaceIntroduceTemplate();
|
||||
}
|
||||
}, occurrencesMap);
|
||||
}
|
||||
else {
|
||||
callback.pass(null);
|
||||
final Settings settings = showDialog(context);
|
||||
if (settings == null) return false;
|
||||
|
||||
CommandProcessor.getInstance().executeCommand(context.getProject(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runRefactoring(context, settings);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, getRefactoringName(), null);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (GrRefactoringError e) {
|
||||
CommonRefactoringUtil
|
||||
.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage(e.getMessage()), getRefactoringName(), getHelpID());
|
||||
CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage(e.getMessage()), getRefactoringName(), getHelpID());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+100
-96
@@ -15,127 +15,118 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.refactoring.introduce.constant;
|
||||
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
|
||||
import com.intellij.refactoring.introduceField.IntroduceConstantHandler;
|
||||
import com.intellij.ui.components.JBCheckBox;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.GrInplaceIntroducer;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.GrAbstractInplaceIntroducer;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContextImpl;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.field.GroovyInplaceFieldValidator;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Max Medvedev on 8/29/13
|
||||
*/
|
||||
public class GrInplaceConstantIntroducer extends GrInplaceIntroducer {
|
||||
public class GrInplaceConstantIntroducer extends GrAbstractInplaceIntroducer<GrIntroduceConstantSettings> {
|
||||
private final GrInplaceIntroduceConstantPanel myPanel;
|
||||
private final GrIntroduceContext myContext;
|
||||
private final RangeMarker myExpressionRangeMarker;
|
||||
private final RangeMarker myStringPartRangeMarker;
|
||||
private final boolean myReplaceAll;
|
||||
private String[] mySuggestedNames;
|
||||
|
||||
public GrInplaceConstantIntroducer(GrVariable var,
|
||||
GrIntroduceContext context,
|
||||
List<RangeMarker> occurrences,
|
||||
boolean replaceAllOccurrences,
|
||||
RangeMarker expressionRangeMarker,
|
||||
RangeMarker stringPartRangeMarker) {
|
||||
super(var, context.getEditor(), context.getProject(), GrIntroduceConstantHandler.REFACTORING_NAME, occurrences, context.getPlace());
|
||||
public GrInplaceConstantIntroducer(GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) {
|
||||
super(IntroduceConstantHandler.REFACTORING_NAME, choice, context);
|
||||
|
||||
myContext = context;
|
||||
myReplaceAll = replaceAllOccurrences;
|
||||
myExpressionRangeMarker = expressionRangeMarker;
|
||||
myStringPartRangeMarker = stringPartRangeMarker;
|
||||
|
||||
myPanel = new GrInplaceIntroduceConstantPanel();
|
||||
|
||||
mySuggestedNames = GroovyNameSuggestionUtil.suggestVariableNames(context.getExpression(), new GroovyInplaceFieldValidator(context),
|
||||
true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinkedHashSet<String> suggestNames(GrIntroduceContext context) {
|
||||
return ContainerUtil.newLinkedHashSet(GroovyNameSuggestionUtil.suggestVariableNames(
|
||||
context.getExpression(),
|
||||
new GroovyInplaceFieldValidator(context),
|
||||
getVariable().hasModifierProperty(PsiModifier.STATIC))
|
||||
);
|
||||
protected String getActionName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void moveOffsetAfter(boolean success) {
|
||||
if (success) {
|
||||
final GrVariable field = getVariable();
|
||||
assert field != null;
|
||||
GrIntroduceConstantProcessor processor = new GrIntroduceConstantProcessor(generateContext(), generateSettings()) {
|
||||
@Override
|
||||
protected GrVariableDeclaration addDeclaration(PsiClass targetClass, GrVariableDeclaration declaration) {
|
||||
return (GrVariableDeclaration)field.getParent();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkErrors(@NotNull PsiClass targetClass) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
processor.run();
|
||||
}
|
||||
super.moveOffsetAfter(success);
|
||||
}
|
||||
|
||||
private GrIntroduceContext generateContext() {
|
||||
final List<RangeMarker> occurrenceMarkers = getOccurrenceMarkers();
|
||||
|
||||
List<PsiElement> occurrences = ContainerUtil.newArrayList();
|
||||
for (RangeMarker marker : occurrenceMarkers) {
|
||||
ContainerUtil.addIfNotNull(occurrences, findExpression(marker));
|
||||
}
|
||||
|
||||
GrExpression expr = null;
|
||||
if (myExpressionRangeMarker != null) expr = findExpression(myExpressionRangeMarker);
|
||||
if (myStringPartRangeMarker != null) {
|
||||
expr = findExpressionFromStringPartMarker(myStringPartRangeMarker);
|
||||
occurrences.add(expr);
|
||||
}
|
||||
|
||||
return new GrIntroduceContextImpl(myContext.getProject(), myContext.getEditor(), expr, null, null, PsiUtilCore.toPsiElementArray(
|
||||
occurrences), myContext.getScope());
|
||||
protected String[] suggestNames(boolean replaceAll, @Nullable GrVariable variable) {
|
||||
return mySuggestedNames;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private GrExpression findExpressionFromStringPartMarker(RangeMarker marker) {
|
||||
PsiFile file = PsiDocumentManager.getInstance(myContext.getProject()).getPsiFile(marker.getDocument());
|
||||
if (file == null) return null;
|
||||
PsiElement leaf = file.findElementAt(marker.getStartOffset());
|
||||
GrBinaryExpression binary = PsiTreeUtil.getParentOfType(leaf, GrBinaryExpression.class);
|
||||
if (binary != null) {
|
||||
return binary.getRightOperand();
|
||||
@Override
|
||||
protected JComponent getComponent() {
|
||||
return myPanel.getRootPane();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveSettings(@NotNull GrVariable variable) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GrVariable runRefactoring(GrIntroduceContext context, GrIntroduceConstantSettings settings, boolean processUsages) {
|
||||
if (processUsages) {
|
||||
return new GrIntroduceConstantProcessor(context, settings).run();
|
||||
}
|
||||
else {
|
||||
PsiElement scope = context.getScope();
|
||||
return new GrIntroduceConstantProcessor(context, settings).addDeclaration(scope instanceof GroovyFileBase ? ((GroovyFileBase)scope).getScriptClass() : (PsiClass)scope).getVariables()[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private GrExpression findExpression(@NotNull RangeMarker marker) {
|
||||
PsiFile file = PsiDocumentManager.getInstance(myContext.getProject()).getPsiFile(marker.getDocument());
|
||||
if (file == null) return null;
|
||||
PsiElement leaf = file.findElementAt(marker.getStartOffset());
|
||||
if (leaf != null && leaf.getParent() instanceof GrReferenceExpression) {
|
||||
return (GrExpression)leaf.getParent();
|
||||
}
|
||||
return null;
|
||||
@Override
|
||||
protected GrIntroduceConstantSettings getInitialSettingsForInplace(@NotNull final GrIntroduceContext context,
|
||||
@NotNull final OccurrencesChooser.ReplaceChoice choice,
|
||||
final String[] names) {
|
||||
return new GrIntroduceConstantSettings() {
|
||||
@Override
|
||||
public String getVisibilityModifier() {
|
||||
return PsiModifier.PUBLIC;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiClass getTargetClass() {
|
||||
return (PsiClass)context.getScope();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return names[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceAllOccurrences() {
|
||||
return isReplaceAllOccurrences();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiType getSelectedType() {
|
||||
GrExpression expression = context.getExpression();
|
||||
GrVariable var = context.getVar();
|
||||
StringPartInfo stringPart = context.getStringPart();
|
||||
return var != null ? var.getDeclaredType() :
|
||||
expression != null ? expression.getType() :
|
||||
stringPart != null ? stringPart.getLiteral().getType() :
|
||||
null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private GrIntroduceConstantSettings generateSettings() {
|
||||
@Override
|
||||
protected GrIntroduceConstantSettings getSettings() {
|
||||
return new GrIntroduceConstantSettings() {
|
||||
@Override
|
||||
public String getVisibilityModifier() {
|
||||
@@ -145,18 +136,18 @@ public class GrInplaceConstantIntroducer extends GrInplaceIntroducer {
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return getVariable().getName();
|
||||
return getInputName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceAllOccurrences() {
|
||||
return myReplaceAll;
|
||||
return isReplaceAllOccurrences();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiType getSelectedType() {
|
||||
return getVariable().getDeclaredType();
|
||||
return GrInplaceConstantIntroducer.this.getSelectedType();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -167,17 +158,30 @@ public class GrInplaceConstantIntroducer extends GrInplaceIntroducer {
|
||||
};
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected JComponent getComponent() {
|
||||
//return myPanel.getRootPane();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected PsiElement checkLocalScope() {
|
||||
return getVariable().getContainingFile();
|
||||
return ((PsiField)getVariable()).getContainingClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Created by Max Medvedev on 8/29/13
|
||||
*/
|
||||
public class GrInplaceIntroduceConstantPanel {
|
||||
private JBCheckBox myMoveToAnotherClassJBCheckBox;
|
||||
private JPanel myRootPane;
|
||||
private JComponent myPreview;
|
||||
|
||||
public boolean isMoveToAnotherClass() {
|
||||
return myMoveToAnotherClassJBCheckBox.isSelected();
|
||||
}
|
||||
|
||||
public JComponent getRootPane() {
|
||||
return myRootPane;
|
||||
}
|
||||
|
||||
private void createUIComponents() {
|
||||
myPreview = getPreviewComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-4
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.groovy.refactoring.introduce.constant.GrInplaceIntroduceConstantPanel">
|
||||
<grid id="27dc6" binding="myRootPane" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.groovy.refactoring.introduce.constant.GrInplaceConstantIntroducer.GrInplaceIntroduceConstantPanel">
|
||||
<grid id="27dc6" binding="myRootPane" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="500" height="400"/>
|
||||
@@ -10,17 +10,24 @@
|
||||
<children>
|
||||
<vspacer id="3c553">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<component id="1ff44" class="com.intellij.ui.components.JBCheckBox" binding="myMoveToAnotherClassJBCheckBox" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<focusable value="false"/>
|
||||
<requestFocusEnabled value="true"/>
|
||||
<text value="&Move to another class"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="3e5fd" class="javax.swing.JComponent" binding="myPreview" custom-create="true">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
|
||||
+3
-65
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.refactoring.introduce.constant;
|
||||
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.HelpID;
|
||||
@@ -27,16 +26,11 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GrRefactoringError;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.*;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.field.GrFieldNameSuggester;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.field.GroovyInplaceFieldValidator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Maxim.Medvedev
|
||||
@@ -99,65 +93,9 @@ public class GrIntroduceConstantHandler extends GrIntroduceFieldHandlerBase<GrIn
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GrInplaceIntroducer getIntroducer(@NotNull final GrVariable var,
|
||||
@NotNull GrIntroduceContext context,
|
||||
@NotNull GrIntroduceConstantSettings settings,
|
||||
@NotNull List<RangeMarker> occurrenceMarkers,
|
||||
RangeMarker varRangeMarker, RangeMarker expressionRangeMarker,
|
||||
RangeMarker stringPartRangeMarker) {
|
||||
if (varRangeMarker != null) {
|
||||
context.getEditor().getCaretModel().moveToOffset(var.getNameIdentifierGroovy().getTextRange().getStartOffset());
|
||||
}
|
||||
else if (expressionRangeMarker != null) {
|
||||
context.getEditor().getCaretModel().moveToOffset(expressionRangeMarker.getStartOffset());
|
||||
}
|
||||
else if (stringPartRangeMarker != null) {
|
||||
int offset = stringPartRangeMarker.getStartOffset();
|
||||
PsiElement at = var.getContainingFile().findElementAt(offset);
|
||||
GrExpression ref = PsiTreeUtil.getParentOfType(at, GrBinaryExpression.class).getRightOperand();
|
||||
context.getEditor().getCaretModel().moveToOffset(ref.getTextRange().getStartOffset());
|
||||
}
|
||||
|
||||
return new GrInplaceConstantIntroducer(var, context, occurrenceMarkers, settings.replaceAllOccurrences(), expressionRangeMarker, stringPartRangeMarker);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GrIntroduceConstantSettings getSettingsForInplace(final GrIntroduceContext context, final OccurrencesChooser.ReplaceChoice choice) {
|
||||
return new GrIntroduceConstantSettings() {
|
||||
@Override
|
||||
public String getVisibilityModifier() {
|
||||
return PsiModifier.PUBLIC;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiClass getTargetClass() {
|
||||
return (PsiClass)context.getScope();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return new GrFieldNameSuggester(context, new GroovyInplaceFieldValidator(context), false).suggestNames().iterator().next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceAllOccurrences() {
|
||||
return choice == OccurrencesChooser.ReplaceChoice.ALL;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiType getSelectedType() {
|
||||
GrExpression expression = context.getExpression();
|
||||
GrVariable var = context.getVar();
|
||||
StringPartInfo stringPart = context.getStringPart();
|
||||
return var != null ? var.getDeclaredType() :
|
||||
expression != null ? expression.getType() :
|
||||
stringPart != null ? stringPart.getLiteral().getType() :
|
||||
null;
|
||||
}
|
||||
};
|
||||
protected GrAbstractInplaceIntroducer<GrIntroduceConstantSettings> getIntroducer(@NotNull GrIntroduceContext context,
|
||||
OccurrencesChooser.ReplaceChoice choice) {
|
||||
return new GrInplaceConstantIntroducer(context, choice);
|
||||
}
|
||||
|
||||
private static class ConstantChecker extends GroovyRecursiveElementVisitor {
|
||||
|
||||
+3
-3
@@ -69,8 +69,7 @@ public class GrIntroduceConstantProcessor {
|
||||
return null;
|
||||
}
|
||||
|
||||
final GrVariableDeclaration rawDeclaration = createField(targetClass);
|
||||
final GrVariableDeclaration declaration = addDeclaration(targetClass, rawDeclaration);
|
||||
final GrVariableDeclaration declaration = addDeclaration(targetClass);
|
||||
final GrField field = (GrField)declaration.getVariables()[0];
|
||||
|
||||
if (context.getVar() != null) {
|
||||
@@ -102,7 +101,8 @@ public class GrIntroduceConstantProcessor {
|
||||
context.getEditor().getSelectionModel().removeSelection();
|
||||
}
|
||||
|
||||
protected GrVariableDeclaration addDeclaration(PsiClass targetClass, GrVariableDeclaration declaration) {
|
||||
protected GrVariableDeclaration addDeclaration(PsiClass targetClass) {
|
||||
GrVariableDeclaration declaration = createField(targetClass);
|
||||
final GrVariableDeclaration added;
|
||||
if (targetClass instanceof GrEnumTypeDefinition) {
|
||||
final GrEnumConstantList enumConstants = ((GrEnumTypeDefinition)targetClass).getEnumConstantList();
|
||||
|
||||
+121
-106
@@ -17,140 +17,133 @@ package org.jetbrains.plugins.groovy.refactoring.introduce.field;
|
||||
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.refactoring.introduce.inplace.KeyboardComboSwitcher;
|
||||
import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
|
||||
import com.intellij.refactoring.introduceField.IntroduceFieldHandler;
|
||||
import com.intellij.ui.NonFocusableCheckBox;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.GrAbstractInplaceIntroducer;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.GrFinalListener;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.GrInplaceIntroducer;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContextImpl;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.EnumSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public class GrInplaceFieldIntroducer extends GrInplaceIntroducer {
|
||||
private final GrInplaceIntroduceFieldPanel myPanel;
|
||||
private final GrIntroduceContext myContext;
|
||||
private final RangeMarker myExpressionRangeMarker;
|
||||
private final RangeMarker myStringPartRangeMarker;
|
||||
private final GrExpression myInitializer;
|
||||
public class GrInplaceFieldIntroducer extends GrAbstractInplaceIntroducer<GrIntroduceFieldSettings> {
|
||||
private GrInplaceIntroduceFieldPanel myPanel;
|
||||
private final GrFinalListener finalListener;
|
||||
private final boolean myReplaceAll;
|
||||
private String[] mySuggestedNames;
|
||||
private boolean myIsStatic;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected PsiElement checkLocalScope() {
|
||||
return getVariable().getContainingFile();
|
||||
return ((PsiField)getVariable()).getContainingClass();
|
||||
}
|
||||
|
||||
public GrInplaceFieldIntroducer(GrVariable var,
|
||||
GrIntroduceContext context,
|
||||
List<RangeMarker> occurrences,
|
||||
boolean replaceAll,
|
||||
@Nullable RangeMarker expressionRangeMarker,
|
||||
@Nullable RangeMarker stringPartRangeMarker,
|
||||
GrExpression initializer) {
|
||||
super(var, context.getEditor(), context.getProject(), IntroduceFieldHandler.REFACTORING_NAME, occurrences, context.getPlace());
|
||||
|
||||
myContext = context;
|
||||
myReplaceAll = replaceAll;
|
||||
myExpressionRangeMarker = expressionRangeMarker;
|
||||
myStringPartRangeMarker = stringPartRangeMarker;
|
||||
myInitializer = initializer;
|
||||
|
||||
myPanel = new GrInplaceIntroduceFieldPanel(context.getProject(),
|
||||
GrIntroduceFieldHandler.getApplicableInitPlaces(context, replaceAll));
|
||||
public GrInplaceFieldIntroducer(GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) {
|
||||
super(IntroduceFieldHandler.REFACTORING_NAME, choice, context);
|
||||
|
||||
finalListener = new GrFinalListener(myEditor);
|
||||
|
||||
mySuggestedNames = GroovyNameSuggestionUtil.suggestVariableNames(context.getExpression(), new GroovyInplaceFieldValidator(getContext()), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void moveOffsetAfter(boolean success) {
|
||||
if (success) {
|
||||
final GrVariable field = getVariable();
|
||||
assert field != null;
|
||||
GrIntroduceFieldProcessor processor = new GrIntroduceFieldProcessor(generateContext(), generateSettings(), false) {
|
||||
@NotNull
|
||||
@Override
|
||||
protected GrExpression getInitializer() {
|
||||
return myInitializer;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected GrVariableDeclaration insertField(@NotNull PsiClass targetClass, @NotNull GrVariableDeclaration declaration) {
|
||||
return (GrVariableDeclaration)field.getParent();
|
||||
}
|
||||
};
|
||||
processor.run();
|
||||
}
|
||||
super.moveOffsetAfter(success);
|
||||
}
|
||||
|
||||
private GrIntroduceContext generateContext() {
|
||||
final List<RangeMarker> occurrenceMarkers = getOccurrenceMarkers();
|
||||
|
||||
List<PsiElement> occurrences = ContainerUtil.newArrayList();
|
||||
for (RangeMarker marker : occurrenceMarkers) {
|
||||
ContainerUtil.addIfNotNull(occurrences, findExpression(marker));
|
||||
}
|
||||
|
||||
GrExpression expr = null;
|
||||
if (myExpressionRangeMarker != null) expr = findExpression(myExpressionRangeMarker);
|
||||
if (myStringPartRangeMarker != null) {
|
||||
expr = findExpressionFromStringPartMarker(myStringPartRangeMarker);
|
||||
occurrences.add(expr);
|
||||
}
|
||||
|
||||
return new GrIntroduceContextImpl(myContext.getProject(), myContext.getEditor(), expr, null, null, PsiUtilCore.toPsiElementArray(
|
||||
occurrences), myContext.getScope());
|
||||
protected GrVariable runRefactoring(GrIntroduceContext context, GrIntroduceFieldSettings settings, boolean processUsages) {
|
||||
GrIntroduceFieldProcessor processor = new GrIntroduceFieldProcessor(context, settings);
|
||||
return processUsages ? processor.run()
|
||||
: processor.insertField((PsiClass)context.getScope()).getVariables()[0];
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private GrExpression findExpressionFromStringPartMarker(RangeMarker marker) {
|
||||
PsiFile file = PsiDocumentManager.getInstance(myContext.getProject()).getPsiFile(marker.getDocument());
|
||||
if (file == null) return null;
|
||||
PsiElement leaf = file.findElementAt(marker.getStartOffset());
|
||||
GrBinaryExpression binary = PsiTreeUtil.getParentOfType(leaf, GrBinaryExpression.class);
|
||||
if (binary != null) {
|
||||
return binary.getRightOperand();
|
||||
}
|
||||
return null;
|
||||
@Override
|
||||
protected GrIntroduceFieldSettings getInitialSettingsForInplace(@NotNull final GrIntroduceContext context,
|
||||
@NotNull final OccurrencesChooser.ReplaceChoice choice,
|
||||
final String[] names) {
|
||||
return new GrIntroduceFieldSettings() {
|
||||
@Override
|
||||
public boolean declareFinal() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Init initializeIn() {
|
||||
return Init.FIELD_DECLARATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVisibilityModifier() {
|
||||
return PsiModifier.PRIVATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStatic() {
|
||||
boolean hasInstanceInScope = true;
|
||||
PsiClass clazz = (PsiClass)context.getScope();
|
||||
if (replaceAllOccurrences()) {
|
||||
for (PsiElement occurrence : context.getOccurrences()) {
|
||||
if (!PsiUtil.hasEnclosingInstanceInScope(clazz, occurrence, false)) {
|
||||
hasInstanceInScope = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (context.getExpression() != null) {
|
||||
hasInstanceInScope = PsiUtil.hasEnclosingInstanceInScope(clazz, context.getExpression(), false);
|
||||
}
|
||||
else if (context.getStringPart() != null) {
|
||||
hasInstanceInScope = PsiUtil.hasEnclosingInstanceInScope(clazz, context.getStringPart().getLiteral(), false);
|
||||
}
|
||||
|
||||
return !hasInstanceInScope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeLocalVar() {
|
||||
return context.getVar() != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return names[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceAllOccurrences() {
|
||||
return context.getVar() != null || choice == OccurrencesChooser.ReplaceChoice.ALL;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiType getSelectedType() {
|
||||
GrExpression expression = context.getExpression();
|
||||
GrVariable var = context.getVar();
|
||||
StringPartInfo stringPart = context.getStringPart();
|
||||
return var != null ? var.getDeclaredType() :
|
||||
expression != null ? expression.getType() :
|
||||
stringPart != null ? stringPart.getLiteral().getType() :
|
||||
null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private GrExpression findExpression(@NotNull RangeMarker marker) {
|
||||
PsiFile file = PsiDocumentManager.getInstance(myContext.getProject()).getPsiFile(marker.getDocument());
|
||||
if (file == null) return null;
|
||||
PsiElement leaf = file.findElementAt(marker.getStartOffset());
|
||||
if (leaf != null && leaf.getParent() instanceof GrReferenceExpression) {
|
||||
return (GrExpression)leaf.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private GrIntroduceFieldSettings generateSettings() {
|
||||
@Override
|
||||
protected GrIntroduceFieldSettings getSettings() {
|
||||
return new GrIntroduceFieldSettings() {
|
||||
@Override
|
||||
public boolean declareFinal() {
|
||||
@@ -169,7 +162,7 @@ public class GrInplaceFieldIntroducer extends GrInplaceIntroducer {
|
||||
|
||||
@Override
|
||||
public boolean isStatic() {
|
||||
return getVariable().hasModifierProperty(PsiModifier.STATIC);
|
||||
return myIsStatic;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -180,39 +173,57 @@ public class GrInplaceFieldIntroducer extends GrInplaceIntroducer {
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return getVariable().getName();
|
||||
return getInputName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceAllOccurrences() {
|
||||
return myReplaceAll;
|
||||
return isReplaceAllOccurrences();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiType getSelectedType() {
|
||||
return getVariable().getDeclaredType();
|
||||
return GrInplaceFieldIntroducer.this.getSelectedType();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getActionName() {
|
||||
return IntroduceFieldHandler.REFACTORING_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] suggestNames(boolean replaceAll, @Nullable GrVariable variable) {
|
||||
return mySuggestedNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveSettings(@NotNull GrVariable variable) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void restoreState(GrVariable psiField) {
|
||||
myIsStatic = psiField.hasModifierProperty(PsiModifier.STATIC);
|
||||
|
||||
super.restoreState(psiField);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected JComponent getComponent() {
|
||||
myPanel = new GrInplaceIntroduceFieldPanel(myProject, GrIntroduceFieldHandler.getApplicableInitPlaces(getContext(), isReplaceAllOccurrences()));
|
||||
return myPanel.getRootPane();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinkedHashSet<String> suggestNames(GrIntroduceContext context) {
|
||||
return ContainerUtil.newLinkedHashSet(
|
||||
GroovyNameSuggestionUtil.suggestVariableNames(myInitializer, new GroovyInplaceFieldValidator(context), false));
|
||||
}
|
||||
|
||||
public class GrInplaceIntroduceFieldPanel {
|
||||
private final Project myProject;
|
||||
private JPanel myRootPane;
|
||||
private JComboBox myInitCB;
|
||||
private NonFocusableCheckBox myDeclareFinalCB;
|
||||
private JComponent myPreview;
|
||||
|
||||
public GrInplaceIntroduceFieldPanel(Project project, EnumSet<GrIntroduceFieldSettings.Init> initPlaces) {
|
||||
myProject = project;
|
||||
@@ -251,5 +262,9 @@ public class GrInplaceFieldIntroducer extends GrInplaceIntroducer {
|
||||
public boolean isFinal() {
|
||||
return myDeclareFinalCB.isSelected();
|
||||
}
|
||||
|
||||
private void createUIComponents() {
|
||||
myPreview = getPreviewComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-4
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.groovy.refactoring.introduce.field.GrInplaceFieldIntroducer.GrInplaceIntroduceFieldPanel">
|
||||
<grid id="27dc6" binding="myRootPane" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="27dc6" binding="myRootPane" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="540" height="63"/>
|
||||
<xy x="20" y="20" width="540" height="88"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
@@ -11,7 +11,7 @@
|
||||
<grid id="3dec1" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<grid row="1" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
@@ -35,13 +35,18 @@
|
||||
</grid>
|
||||
<component id="23db" class="com.intellij.ui.NonFocusableCheckBox" binding="myDeclareFinalCB">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<horizontalAlignment value="10"/>
|
||||
<text value="Declare &final"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="d8bd5" class="javax.swing.JComponent" binding="myPreview" custom-create="true">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
|
||||
+14
-112
@@ -16,25 +16,21 @@
|
||||
package org.jetbrains.plugins.groovy.refactoring.introduce.field;
|
||||
|
||||
import com.intellij.codeInsight.TestFrameworks;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.HelpID;
|
||||
import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
|
||||
import com.intellij.refactoring.introduceField.IntroduceFieldHandler;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GrRefactoringError;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
|
||||
@@ -100,133 +96,39 @@ public class GrIntroduceFieldHandler extends GrIntroduceFieldHandlerBase<GrIntro
|
||||
|
||||
@Override
|
||||
public GrVariable runRefactoring(@NotNull GrIntroduceContext context, @NotNull GrIntroduceFieldSettings settings) {
|
||||
return new GrIntroduceFieldProcessor(context, settings, isInplace(context.getEditor(), context.getPlace())).run();
|
||||
return new GrIntroduceFieldProcessor(context, settings).run();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GrInplaceFieldIntroducer getIntroducer(@NotNull final GrVariable var,
|
||||
@NotNull GrIntroduceContext context,
|
||||
@NotNull GrIntroduceFieldSettings settings,
|
||||
@NotNull List<RangeMarker> occurrenceMarkers,
|
||||
@Nullable RangeMarker varRangeMarker,
|
||||
@Nullable RangeMarker expressionRangeMarker,
|
||||
@Nullable RangeMarker stringPartRangeMarker) {
|
||||
if (varRangeMarker != null) {
|
||||
context.getEditor().getCaretModel().moveToOffset(var.getNameIdentifierGroovy().getTextRange().getStartOffset());
|
||||
}
|
||||
else if (expressionRangeMarker != null) {
|
||||
context.getEditor().getCaretModel().moveToOffset(expressionRangeMarker.getStartOffset());
|
||||
}
|
||||
else if (stringPartRangeMarker != null) {
|
||||
int offset = stringPartRangeMarker.getStartOffset();
|
||||
PsiElement at = var.getContainingFile().findElementAt(offset);
|
||||
GrExpression ref = PsiTreeUtil.getParentOfType(at, GrBinaryExpression.class).getRightOperand();
|
||||
context.getEditor().getCaretModel().moveToOffset(ref.getTextRange().getStartOffset());
|
||||
}
|
||||
GrExpression initializer =
|
||||
GroovyPsiElementFactory.getInstance(context.getProject()).createExpressionFromText(var.getInitializerGroovy().getText());
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
var.setInitializerGroovy(null);
|
||||
}
|
||||
});
|
||||
|
||||
return new GrInplaceFieldIntroducer(var, context, occurrenceMarkers, settings.replaceAllOccurrences(), expressionRangeMarker,
|
||||
stringPartRangeMarker, initializer);
|
||||
@Override
|
||||
protected GrAbstractInplaceIntroducer<GrIntroduceFieldSettings> getIntroducer(@NotNull GrIntroduceContext context,
|
||||
OccurrencesChooser.ReplaceChoice choice) {
|
||||
return new GrInplaceFieldIntroducer(context, choice);
|
||||
}
|
||||
|
||||
static EnumSet<GrIntroduceFieldSettings.Init> getApplicableInitPlaces(GrIntroduceContext context, boolean replaceAll) {
|
||||
EnumSet<GrIntroduceFieldSettings.Init> result = EnumSet.of(GrIntroduceFieldSettings.Init.FIELD_DECLARATION,
|
||||
GrIntroduceFieldSettings.Init.CONSTRUCTOR);
|
||||
EnumSet<GrIntroduceFieldSettings.Init> result = EnumSet.of(GrIntroduceFieldSettings.Init.FIELD_DECLARATION);
|
||||
|
||||
if (!(context.getScope() instanceof GroovyScriptClass || context.getScope() instanceof GroovyFileBase)) {
|
||||
result.add(GrIntroduceFieldSettings.Init.CONSTRUCTOR);
|
||||
}
|
||||
|
||||
GrTypeDefinition clazz = (GrTypeDefinition)context.getScope();
|
||||
PsiElement scope = context.getScope();
|
||||
|
||||
if (replaceAll) {
|
||||
PsiElement anchor = GrIntroduceHandlerBase.findAnchor(context.getOccurrences(), clazz);
|
||||
PsiElement anchor = GrIntroduceHandlerBase.findAnchor(context.getOccurrences(), scope);
|
||||
if (anchor != null) {
|
||||
result.add(GrIntroduceFieldSettings.Init.CUR_METHOD);
|
||||
}
|
||||
}
|
||||
|
||||
if (TestFrameworks.getInstance().isTestClass(clazz)) {
|
||||
if (scope instanceof GrTypeDefinition && TestFrameworks.getInstance().isTestClass((PsiClass)scope)) {
|
||||
result.add(GrIntroduceFieldSettings.Init.SETUP_METHOD);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GrIntroduceFieldSettings getSettingsForInplace(final GrIntroduceContext context, final OccurrencesChooser.ReplaceChoice choice) {
|
||||
return new GrIntroduceFieldSettings() {
|
||||
@Override
|
||||
public boolean declareFinal() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Init initializeIn() {
|
||||
return Init.FIELD_DECLARATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVisibilityModifier() {
|
||||
return PsiModifier.PRIVATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStatic() {
|
||||
boolean hasInstanceInScope = true;
|
||||
PsiClass clazz = (PsiClass)context.getScope();
|
||||
if (replaceAllOccurrences()) {
|
||||
for (PsiElement occurrence : context.getOccurrences()) {
|
||||
if (!PsiUtil.hasEnclosingInstanceInScope(clazz, occurrence, false)) {
|
||||
hasInstanceInScope = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (context.getExpression() != null) {
|
||||
hasInstanceInScope = PsiUtil.hasEnclosingInstanceInScope(clazz, context.getExpression(), false);
|
||||
}
|
||||
else if (context.getStringPart() != null) {
|
||||
hasInstanceInScope = PsiUtil.hasEnclosingInstanceInScope(clazz, context.getStringPart().getLiteral(), false);
|
||||
}
|
||||
|
||||
return !hasInstanceInScope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeLocalVar() {
|
||||
return context.getVar() != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return new GrFieldNameSuggester(context, new GroovyInplaceFieldValidator(context), false).suggestNames().iterator().next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceAllOccurrences() {
|
||||
return context.getVar() != null || choice == OccurrencesChooser.ReplaceChoice.ALL;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiType getSelectedType() {
|
||||
GrExpression expression = context.getExpression();
|
||||
GrVariable var = context.getVar();
|
||||
StringPartInfo stringPart = context.getStringPart();
|
||||
return var != null ? var.getDeclaredType() :
|
||||
expression != null ? expression.getType() :
|
||||
stringPart != null ? stringPart.getLiteral().getType() :
|
||||
null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected PsiElement[] findOccurrences(@NotNull GrExpression expression, @NotNull PsiElement scope) {
|
||||
|
||||
+14
-11
@@ -25,8 +25,10 @@ import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.codeStyle.GrReferenceAdjuster;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrQualifiedReference;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
|
||||
@@ -62,19 +64,19 @@ public class GrIntroduceFieldProcessor {
|
||||
|
||||
private final GrIntroduceContext context;
|
||||
private final GrIntroduceFieldSettings settings;
|
||||
private boolean myForInplacePrepare;
|
||||
|
||||
public GrIntroduceFieldProcessor(@NotNull GrIntroduceContext context, @NotNull GrIntroduceFieldSettings settings, boolean forInplacePrepare) {
|
||||
public GrIntroduceFieldProcessor(@NotNull GrIntroduceContext context,
|
||||
@NotNull GrIntroduceFieldSettings settings) {
|
||||
this.context = context;
|
||||
this.settings = settings;
|
||||
myForInplacePrepare = forInplacePrepare;
|
||||
}
|
||||
|
||||
public GrVariable run() {
|
||||
final PsiClass targetClass = (PsiClass)context.getScope();
|
||||
PsiElement scope = context.getScope();
|
||||
final PsiClass targetClass = scope instanceof GroovyFileBase ? ((GroovyFileBase)scope).getScriptClass() : (PsiClass)scope;
|
||||
if (targetClass == null) return null;
|
||||
|
||||
final GrVariableDeclaration declaration = insertField(targetClass, createField());
|
||||
final GrVariableDeclaration declaration = insertField(targetClass);
|
||||
final GrVariable field = declaration.getVariables()[0];
|
||||
|
||||
switch (settings.initializeIn()) {
|
||||
@@ -119,7 +121,7 @@ public class GrIntroduceFieldProcessor {
|
||||
else {
|
||||
final GrExpression expression = context.getExpression();
|
||||
assert expression != null;
|
||||
if (!myForInplacePrepare && PsiUtil.isExpressionStatement(expression)) {
|
||||
if (PsiUtil.isExpressionStatement(expression)) {
|
||||
expression.delete();
|
||||
}
|
||||
else {
|
||||
@@ -135,7 +137,8 @@ public class GrIntroduceFieldProcessor {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected GrVariableDeclaration insertField(@NotNull PsiClass targetClass, @NotNull GrVariableDeclaration declaration) {
|
||||
protected GrVariableDeclaration insertField(@NotNull PsiClass targetClass) {
|
||||
GrVariableDeclaration declaration = createField(targetClass);
|
||||
if (targetClass instanceof GrEnumTypeDefinition) {
|
||||
final GrEnumConstantList enumConstants = ((GrEnumTypeDefinition)targetClass).getEnumConstantList();
|
||||
return (GrVariableDeclaration)targetClass.addAfter(declaration, enumConstants);
|
||||
@@ -304,7 +307,7 @@ public class GrIntroduceFieldProcessor {
|
||||
}
|
||||
|
||||
if (replaced instanceof GrQualifiedReference<?>) {
|
||||
org.jetbrains.plugins.groovy.codeStyle.GrReferenceAdjuster.shortenReference((GrQualifiedReference<?>)replaced);
|
||||
GrReferenceAdjuster.shortenReference((GrQualifiedReference<?>)replaced);
|
||||
}
|
||||
if (isOriginal) {
|
||||
updateCaretPosition(replaced);
|
||||
@@ -326,13 +329,13 @@ public class GrIntroduceFieldProcessor {
|
||||
return GroovyPsiElementFactory.getInstance(place.getProject()).createReferenceExpressionFromText(refText, place);
|
||||
}
|
||||
|
||||
private GrVariableDeclaration createField() {
|
||||
private GrVariableDeclaration createField(PsiClass targetClass) {
|
||||
final String name = settings.getName();
|
||||
final PsiType type = settings.getSelectedType();
|
||||
final String modifier = settings.getVisibilityModifier();
|
||||
|
||||
List<String> modifiers = new ArrayList<String>();
|
||||
if (context.getScope() instanceof GroovyScriptClass) {
|
||||
if (targetClass instanceof GroovyScriptClass) {
|
||||
modifiers.add("@" + GroovyCommonClassNames.GROOVY_TRANSFORM_FIELD);
|
||||
}
|
||||
if (settings.isStatic()) modifiers.add(PsiModifier.STATIC);
|
||||
@@ -341,7 +344,7 @@ public class GrIntroduceFieldProcessor {
|
||||
|
||||
final String[] arr_modifiers = ArrayUtil.toStringArray(modifiers);
|
||||
final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(context.getProject());
|
||||
if (context.getScope() instanceof GroovyScriptClass) {
|
||||
if (targetClass instanceof GroovyScriptClass) {
|
||||
return factory.createVariableDeclaration(arr_modifiers, ((GrExpression)null), type, name);
|
||||
}
|
||||
else {
|
||||
|
||||
+118
-30
@@ -16,25 +16,31 @@
|
||||
package org.jetbrains.plugins.groovy.refactoring.introduce.variable;
|
||||
|
||||
import com.intellij.codeInsight.template.TemplateBuilderImpl;
|
||||
import com.intellij.openapi.actionSystem.Shortcut;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.keymap.Keymap;
|
||||
import com.intellij.openapi.keymap.KeymapManager;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
|
||||
import com.intellij.refactoring.util.CanonicalTypes;
|
||||
import com.intellij.ui.NonFocusableCheckBox;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SupertypeConstraint;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.GrAbstractInplaceIntroducer;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.GrFinalListener;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.GrInplaceIntroducer;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo;
|
||||
import org.jetbrains.plugins.groovy.settings.GroovyApplicationSettings;
|
||||
import org.jetbrains.plugins.groovy.template.expressions.ChooseTypeExpression;
|
||||
|
||||
@@ -42,30 +48,40 @@ import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
* Created by Max Medvedev on 10/29/13
|
||||
*/
|
||||
public class GrInplaceVariableIntroducer extends GrInplaceIntroducer {
|
||||
public abstract class GrInplaceVariableIntroducer extends GrAbstractInplaceIntroducer<GroovyIntroduceVariableSettings> {
|
||||
private JCheckBox myCanBeFinalCb;
|
||||
|
||||
public GrInplaceVariableIntroducer(GrVariable elementToRename,
|
||||
Editor editor,
|
||||
Project project,
|
||||
String title,
|
||||
List<RangeMarker> occurrences,
|
||||
@Nullable PsiElement elementToIntroduce) {
|
||||
super(elementToRename, editor, project, title, occurrences, elementToIntroduce);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinkedHashSet<String> suggestNames(GrIntroduceContext context) {
|
||||
return ContainerUtil.newLinkedHashSet(GroovyNameSuggestionUtil.suggestVariableNames(getVariable().getInitializerGroovy(), new GroovyVariableValidator(context)));
|
||||
public GrInplaceVariableIntroducer(String title,
|
||||
OccurrencesChooser.ReplaceChoice replaceChoice,
|
||||
GrIntroduceContext context) {
|
||||
super(title, replaceChoice, context);
|
||||
setAdvertisementText(getAdvertisementText());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getAdvertisementText() {
|
||||
final Keymap keymap = KeymapManager.getInstance().getActiveKeymap();
|
||||
final Shortcut[] shortcuts = keymap.getShortcuts("PreviousTemplateVariable");
|
||||
if (shortcuts.length > 0) {
|
||||
return "Press " + KeymapUtil.getShortcutText(shortcuts[0]) + " to change type";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getActionName() {
|
||||
return GrIntroduceVariableHandler.REFACTORING_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] suggestNames(boolean replaceAll, @Nullable GrVariable variable) {
|
||||
return GroovyNameSuggestionUtil.suggestVariableNames(getContext().getExpression(), new GroovyVariableValidator(getContext()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent getComponent() {
|
||||
myCanBeFinalCb = new NonFocusableCheckBox("Declare final");
|
||||
@@ -91,22 +107,58 @@ public class GrInplaceVariableIntroducer extends GrInplaceIntroducer {
|
||||
panel.setBorder(null);
|
||||
|
||||
if (myCanBeFinalCb != null) {
|
||||
panel.add(myCanBeFinalCb, new GridBagConstraints(0, 1, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
|
||||
panel.add(myCanBeFinalCb, new GridBagConstraints(0, 1, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,
|
||||
new Insets(5, 5, 5, 5), 0, 0));
|
||||
}
|
||||
|
||||
panel.add(Box.createVerticalBox(), new GridBagConstraints(0, 2, 1, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0,0,0,0), 0,0));
|
||||
panel.add(Box.createVerticalBox(),
|
||||
new GridBagConstraints(0, 2, 1, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
|
||||
|
||||
return panel;
|
||||
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public void finish(boolean success) {
|
||||
super.finish(success);
|
||||
protected GroovyIntroduceVariableSettings getInitialSettingsForInplace(@NotNull final GrIntroduceContext context,
|
||||
@NotNull final OccurrencesChooser.ReplaceChoice choice,
|
||||
final String[] names) {
|
||||
return new GroovyIntroduceVariableSettings() {
|
||||
private final CanonicalTypes.Type myType;
|
||||
|
||||
if (success) {
|
||||
GroovyApplicationSettings.getInstance().INTRODUCE_LOCAL_SELECT_DEF = getVariable().getDeclaredType() == null;
|
||||
}
|
||||
{
|
||||
GrExpression expression = context.getExpression();
|
||||
StringPartInfo stringPart = context.getStringPart();
|
||||
GrVariable var = context.getVar();
|
||||
PsiType type = expression != null ? expression.getType() :
|
||||
var != null ? var.getType() :
|
||||
stringPart != null ? stringPart.getLiteral().getType() :
|
||||
null;
|
||||
myType = type != null ? CanonicalTypes.createTypeWrapper(type) : null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isDeclareFinal() {
|
||||
return myCanBeFinalCb != null ? myCanBeFinalCb.isSelected() : false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return names[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceAllOccurrences() {
|
||||
return choice == OccurrencesChooser.ReplaceChoice.ALL;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiType getSelectedType() {
|
||||
return myType != null ? myType.getType(context.getPlace(), context.getPlace().getManager()) : null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -119,4 +171,40 @@ public class GrInplaceVariableIntroducer extends GrInplaceIntroducer {
|
||||
: PsiUtil.findModifierInList(variable.getModifierList(), GrModifier.DEF);
|
||||
builder.replaceElement(element, "Variable_type", typeExpression, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
protected GroovyIntroduceVariableSettings getSettings() {
|
||||
return new GroovyIntroduceVariableSettings() {
|
||||
@Override
|
||||
public boolean isDeclareFinal() {
|
||||
return myCanBeFinalCb.isSelected();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return GrInplaceVariableIntroducer.this.getInputName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceAllOccurrences() {
|
||||
return isReplaceAllOccurrences();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiType getSelectedType() {
|
||||
return GrInplaceVariableIntroducer.this.getSelectedType();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveSettings(@NotNull GrVariable variable) {
|
||||
GroovyApplicationSettings.getInstance().INTRODUCE_LOCAL_SELECT_DEF = variable.getDeclaredType() == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getCaretOffset() {
|
||||
return getVariable().getNameIdentifierGroovy().getTextRange().getEndOffset();
|
||||
}
|
||||
}
|
||||
+6
-8
@@ -46,26 +46,26 @@ import java.util.List;
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public class GrIntroduceLocalVariableProcessor {
|
||||
public abstract class GrIntroduceLocalVariableProcessor {
|
||||
private static final Logger LOG = Logger.getInstance(GrIntroduceLocalVariableProcessor.class);
|
||||
|
||||
private final GrIntroduceContext myContext;
|
||||
private final GroovyIntroduceVariableSettings mySettings;
|
||||
private final boolean myProcessUsages;
|
||||
private final PsiElement[] myOccurrences;
|
||||
private GrExpression myExpression;
|
||||
private final GrIntroduceVariableHandler myHandler;
|
||||
|
||||
public GrIntroduceLocalVariableProcessor(@NotNull GrIntroduceContext context,
|
||||
@NotNull GroovyIntroduceVariableSettings settings,
|
||||
@NotNull PsiElement[] occurrences,
|
||||
@NotNull GrExpression expression,
|
||||
@NotNull GrIntroduceVariableHandler handler) {
|
||||
boolean processUsages) {
|
||||
|
||||
myContext = context;
|
||||
mySettings = settings;
|
||||
myProcessUsages = processUsages;
|
||||
myOccurrences = settings.replaceAllOccurrences() ? occurrences : new PsiElement[]{expression};
|
||||
myExpression = expression;
|
||||
myHandler = handler;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -75,7 +75,7 @@ public class GrIntroduceLocalVariableProcessor {
|
||||
preprocessOccurrences();
|
||||
|
||||
int expressionIndex = ArrayUtilRt.find(myOccurrences, myExpression);
|
||||
final PsiElement[] replaced = processOccurrences();
|
||||
final PsiElement[] replaced = myProcessUsages ? processOccurrences() : myOccurrences;
|
||||
PsiElement replacedExpression = replaced[expressionIndex];
|
||||
GrStatement anchor = getAnchor(replaced);
|
||||
|
||||
@@ -84,9 +84,7 @@ public class GrIntroduceLocalVariableProcessor {
|
||||
return insertVariableDefinition(declaration, anchor, replacedExpression);
|
||||
}
|
||||
|
||||
private void refreshPositionMarker(PsiElement e) {
|
||||
myHandler.refreshPositionMarker(myContext.getEditor().getDocument().createRangeMarker(e.getTextRange()));
|
||||
}
|
||||
protected abstract void refreshPositionMarker(PsiElement e);
|
||||
|
||||
private static boolean isControlStatementBranch(GrStatement statement) {
|
||||
return statement.getParent() instanceof GrLoopStatement && statement == ((GrLoopStatement)statement.getParent()).getBody() ||
|
||||
|
||||
+19
-84
@@ -13,24 +13,16 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.plugins.groovy.refactoring.introduce.variable;
|
||||
|
||||
import com.intellij.openapi.actionSystem.Shortcut;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.keymap.Keymap;
|
||||
import com.intellij.openapi.keymap.KeymapManager;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.openapi.util.Pass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.refactoring.HelpID;
|
||||
import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
|
||||
import com.intellij.refactoring.util.CanonicalTypes;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
|
||||
@@ -48,10 +40,8 @@ import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
* Created by Max Medvedev on 10/29/13
|
||||
*/
|
||||
public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase<GroovyIntroduceVariableSettings, GrControlFlowOwner> {
|
||||
public static final String DUMMY_NAME = "________________xxx_________________";
|
||||
@@ -129,8 +119,7 @@ public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase<GroovyInt
|
||||
public GrVariable runRefactoring(@NotNull final GrIntroduceContext context, @NotNull final GroovyIntroduceVariableSettings settings) {
|
||||
// Generating variable declaration
|
||||
|
||||
final GrVariableDeclaration varDecl = generateDeclaration(context, settings);
|
||||
GrVariable insertedVar = processExpression(context, settings, varDecl);
|
||||
GrVariable insertedVar = processExpression(context, settings, true);
|
||||
|
||||
if (context.getEditor() != null && getPositionMarker() != null) {
|
||||
context.getEditor().getCaretModel().moveToOffset(getPositionMarker().getEndOffset());
|
||||
@@ -140,72 +129,11 @@ public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase<GroovyInt
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GrInplaceVariableIntroducer getIntroducer(@NotNull GrVariable var,
|
||||
@NotNull GrIntroduceContext context,
|
||||
@NotNull GroovyIntroduceVariableSettings settings,
|
||||
@NotNull List<RangeMarker> occurrenceMarkers,
|
||||
RangeMarker varRangeMarker, RangeMarker expressionRangeMarker,
|
||||
RangeMarker stringPartRangeMarker) {
|
||||
context.getEditor().getCaretModel().moveToOffset(var.getTextOffset());
|
||||
GrInplaceVariableIntroducer introducer = new GrInplaceVariableIntroducer(var, context.getEditor(), context.getProject(), REFACTORING_NAME, occurrenceMarkers, var);
|
||||
introducer.setAdvertisementText(getAdvertisementText(var.getDeclaredType() != null));
|
||||
|
||||
return introducer;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getAdvertisementText(final boolean hasTypeSuggestion) {
|
||||
final Keymap keymap = KeymapManager.getInstance().getActiveKeymap();
|
||||
if (hasTypeSuggestion) {
|
||||
final Shortcut[] shortcuts = keymap.getShortcuts("PreviousTemplateVariable");
|
||||
if (shortcuts.length > 0) {
|
||||
return "Press " + KeymapUtil.getShortcutText(shortcuts[0]) + " to change type";
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GroovyIntroduceVariableSettings getSettingsForInplace(final GrIntroduceContext context, final OccurrencesChooser.ReplaceChoice choice) {
|
||||
return new GroovyIntroduceVariableSettings() {
|
||||
private final CanonicalTypes.Type myType;
|
||||
private final String myName;
|
||||
|
||||
|
||||
{
|
||||
GrExpression expression = context.getExpression();
|
||||
StringPartInfo stringPart = context.getStringPart();
|
||||
GrVariable var = context.getVar();
|
||||
PsiType type = expression != null ? expression.getType() :
|
||||
var != null ? var.getType() :
|
||||
stringPart != null ? stringPart.getLiteral().getType() :
|
||||
null;
|
||||
myType = type != null ?CanonicalTypes.createTypeWrapper(type) : null;
|
||||
|
||||
myName = new GrVariableNameSuggester(context, new GroovyVariableValidator(context)).suggestNames().iterator().next();
|
||||
}
|
||||
|
||||
|
||||
protected GrInplaceVariableIntroducer getIntroducer(@NotNull GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) {
|
||||
return new GrInplaceVariableIntroducer(getRefactoringName(), choice, context) {
|
||||
@Override
|
||||
public boolean isDeclareFinal() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceAllOccurrences() {
|
||||
return choice == OccurrencesChooser.ReplaceChoice.ALL;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiType getSelectedType() {
|
||||
return myType != null ? myType.getType(context.getPlace(), context.getPlace().getManager()) : null;
|
||||
protected GrVariable runRefactoring(GrIntroduceContext context, GroovyIntroduceVariableSettings settings, boolean processUsages) {
|
||||
return processExpression(context, settings, processUsages);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -231,24 +159,31 @@ public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase<GroovyInt
|
||||
@NotNull
|
||||
private GrVariable processExpression(@NotNull GrIntroduceContext context,
|
||||
@NotNull GroovyIntroduceVariableSettings settings,
|
||||
@NotNull GrVariableDeclaration varDecl) {
|
||||
boolean processUsages) {
|
||||
GrVariableDeclaration varDecl = generateDeclaration(context, settings);
|
||||
|
||||
if (context.getStringPart() != null) {
|
||||
final GrExpression ref = processLiteral(DUMMY_NAME, context.getStringPart(), context.getProject());
|
||||
return doProcessExpression(context, settings, varDecl, new PsiElement[]{ref}, ref);
|
||||
return doProcessExpression(context, settings, varDecl, new PsiElement[]{ref}, ref, processUsages);
|
||||
}
|
||||
else {
|
||||
final GrExpression expression = context.getExpression();
|
||||
assert expression != null;
|
||||
return doProcessExpression(context, settings, varDecl, context.getOccurrences(), expression);
|
||||
return doProcessExpression(context, settings, varDecl, context.getOccurrences(), expression, processUsages);
|
||||
}
|
||||
}
|
||||
|
||||
private GrVariable doProcessExpression(@NotNull GrIntroduceContext context,
|
||||
private GrVariable doProcessExpression(@NotNull final GrIntroduceContext context,
|
||||
@NotNull GroovyIntroduceVariableSettings settings,
|
||||
@NotNull GrVariableDeclaration varDecl,
|
||||
@NotNull PsiElement[] elements,
|
||||
@NotNull GrExpression expression) {
|
||||
return new GrIntroduceLocalVariableProcessor(context, settings, elements, expression, this).processExpression(varDecl);
|
||||
@NotNull GrExpression expression, boolean processUsages) {
|
||||
return new GrIntroduceLocalVariableProcessor(context, settings, elements, expression, processUsages) {
|
||||
@Override
|
||||
protected void refreshPositionMarker(PsiElement e) {
|
||||
GrIntroduceVariableHandler.this.refreshPositionMarker(context.getEditor().getDocument().createRangeMarker(e.getTextRange()));
|
||||
}
|
||||
}.processExpression(varDecl);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -109,6 +109,8 @@ public class HgLogProvider implements VcsLogProvider {
|
||||
repository.update();
|
||||
Collection<HgNameWithHashInfo> branches = repository.getBranches();
|
||||
Collection<HgNameWithHashInfo> bookmarks = repository.getBookmarks();
|
||||
Collection<HgNameWithHashInfo> tags = repository.getTags();
|
||||
Collection<HgNameWithHashInfo> localTags = repository.getLocalTags();
|
||||
|
||||
Collection<VcsRef> refs = new ArrayList<VcsRef>(branches.size() + bookmarks.size());
|
||||
|
||||
@@ -123,17 +125,16 @@ public class HgLogProvider implements VcsLogProvider {
|
||||
if (currentRevision != null) { // null => fresh repository
|
||||
refs.add(new VcsRefImpl(myVcsObjectsFactory.createHash(currentRevision), "HEAD", HgRefManager.HEAD, root));
|
||||
}
|
||||
|
||||
//refs.addAll(readTags(root));
|
||||
for (HgNameWithHashInfo tagInfo : tags) {
|
||||
refs.add(new VcsRefImpl(myVcsObjectsFactory.createHash(tagInfo.getHash()), tagInfo.getName(), HgRefManager.TAG, root));
|
||||
}
|
||||
for (HgNameWithHashInfo localTagInfo : localTags) {
|
||||
refs.add(new VcsRefImpl(myVcsObjectsFactory.createHash(localTagInfo.getHash()), localTagInfo.getName(),
|
||||
HgRefManager.LOCAL_TAG, root));
|
||||
}
|
||||
return refs;
|
||||
}
|
||||
|
||||
//todo implement
|
||||
/* @NotNull
|
||||
private Collection<? extends VcsRef> readTags(@NotNull VirtualFile root) throws VcsException {
|
||||
return Collections.emptyList();
|
||||
}*/
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public VcsKey getSupportedVcs() {
|
||||
|
||||
@@ -38,11 +38,13 @@ public class HgRefManager implements VcsLogRefManager {
|
||||
private static final Color BRANCH_COLOR = new JBColor(new Color(0x75eec7), new Color(0x0D6D4F));
|
||||
private static final Color BOOKMARK_COLOR = new JBColor(new Color(0xbcbcfc), new Color(0xbcbcfc).darker().darker());
|
||||
private static final Color TAG_COLOR = JBColor.WHITE;
|
||||
private static final Color LOCAL_TAG_COLOR = JBColor.CYAN;
|
||||
|
||||
public static final VcsRefType HEAD = new SimpleRefType(true, HEAD_COLOR);
|
||||
public static final VcsRefType BRANCH = new SimpleRefType(true, BRANCH_COLOR);
|
||||
public static final VcsRefType BOOKMARK = new SimpleRefType(true, BOOKMARK_COLOR);
|
||||
public static final VcsRefType TAG = new SimpleRefType(false, TAG_COLOR);
|
||||
public static final VcsRefType LOCAL_TAG = new SimpleRefType(false, LOCAL_TAG_COLOR);
|
||||
|
||||
// first has the highest priority
|
||||
private static final List<VcsRefType> REF_TYPE_PRIORITIES = Arrays.asList(HEAD, BRANCH, BOOKMARK, TAG);
|
||||
@@ -103,7 +105,6 @@ public class HgRefManager implements VcsLogRefManager {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<RefGroup> group(Collection<VcsRef> refs) {
|
||||
// TODO group non-tracking refs into remotes
|
||||
return ContainerUtil.map(sort(refs), new Function<VcsRef, RefGroup>() {
|
||||
@Override
|
||||
public RefGroup fun(final VcsRef ref) {
|
||||
|
||||
@@ -36,19 +36,25 @@ public class HgRepoInfo {
|
||||
@Nullable private String myCurrentBookmark = null;
|
||||
@NotNull private Set<HgNameWithHashInfo> myBranches = Collections.emptySet();
|
||||
@NotNull private Set<HgNameWithHashInfo> myBookmarks = Collections.emptySet();
|
||||
@NotNull private Set<HgNameWithHashInfo> myTags = Collections.emptySet();
|
||||
@NotNull private Set<HgNameWithHashInfo> myLocalTags = Collections.emptySet();
|
||||
|
||||
public HgRepoInfo(@NotNull String currentBranch,
|
||||
@Nullable String currentRevision,
|
||||
@NotNull Repository.State state,
|
||||
@NotNull Collection<HgNameWithHashInfo> branches,
|
||||
@NotNull Collection<HgNameWithHashInfo> bookmarks,
|
||||
@Nullable String currentBookmark) {
|
||||
@Nullable String currentBookmark,
|
||||
@NotNull Collection<HgNameWithHashInfo> tags,
|
||||
@NotNull Collection<HgNameWithHashInfo> localTags) {
|
||||
myCurrentBranch = currentBranch;
|
||||
myCurrentRevision = currentRevision;
|
||||
myState = state;
|
||||
myBranches = new LinkedHashSet<HgNameWithHashInfo>(branches);
|
||||
myBookmarks = new LinkedHashSet<HgNameWithHashInfo>(bookmarks);
|
||||
myCurrentBookmark = currentBookmark;
|
||||
myTags = new LinkedHashSet<HgNameWithHashInfo>(tags);
|
||||
myLocalTags = new LinkedHashSet<HgNameWithHashInfo>(localTags);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -66,6 +72,16 @@ public class HgRepoInfo {
|
||||
return myBookmarks;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<HgNameWithHashInfo> getTags() {
|
||||
return myTags;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<HgNameWithHashInfo> getLocalTags() {
|
||||
return myLocalTags;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getCurrentRevision() {
|
||||
return myCurrentRevision;
|
||||
@@ -94,13 +110,15 @@ public class HgRepoInfo {
|
||||
if (myCurrentBookmark != null ? !myCurrentBookmark.equals(info.myCurrentBookmark) : info.myCurrentBookmark != null) return false;
|
||||
if (!myBranches.equals(info.myBranches)) return false;
|
||||
if (!myBookmarks.equals(info.myBookmarks)) return false;
|
||||
if (!myTags.equals(info.myTags)) return false;
|
||||
if (!myLocalTags.equals(info.myLocalTags)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(myCurrentBranch, myCurrentRevision, myCurrentBookmark, myState, myBranches, myBookmarks);
|
||||
return Objects.hashCode(myCurrentBranch, myCurrentRevision, myCurrentBookmark, myState, myBranches, myBookmarks, myTags, myLocalTags);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -44,6 +44,12 @@ public interface HgRepository extends Repository {
|
||||
@NotNull
|
||||
Collection<HgNameWithHashInfo> getBookmarks();
|
||||
|
||||
@NotNull
|
||||
Collection<HgNameWithHashInfo> getTags();
|
||||
|
||||
@NotNull
|
||||
Collection<HgNameWithHashInfo> getLocalTags();
|
||||
|
||||
@Nullable
|
||||
String getCurrentBookmark();
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@ public class HgRepositoryFiles {
|
||||
public static final String MERGE = "merge";
|
||||
public static final String BRANCH = "branch";
|
||||
public static final String BOOKMARKS = "bookmarks";
|
||||
public static final String LOCAL_TAGS = "localtags";
|
||||
public static final String TAGS = ".hgtags";
|
||||
public static final String CURRENT_BOOKMARK = "bookmarks.current";
|
||||
public static final String CONFIG_HGRC = "hgrc";
|
||||
|
||||
@@ -45,6 +47,8 @@ public class HgRepositoryFiles {
|
||||
@NotNull private final String myMergePath;
|
||||
@NotNull private final String myBranchPath;
|
||||
@NotNull private final String myBookmarksPath;
|
||||
@NotNull private final String myTagsPath;
|
||||
@NotNull private final String myLocalTagsPath;
|
||||
@NotNull private final String myCurrentBookmarkPath;
|
||||
@NotNull private final String myConfigHgrcPath;
|
||||
|
||||
@@ -59,6 +63,8 @@ public class HgRepositoryFiles {
|
||||
myBranchPath = hgDir.getPath() + slash(BRANCH);
|
||||
myMergePath = hgDir.getPath() + slash(MERGE);
|
||||
myBookmarksPath = hgDir.getPath() + slash(BOOKMARKS);
|
||||
myTagsPath = hgDir.getParent().getPath() + slash(TAGS);
|
||||
myLocalTagsPath = hgDir.getPath() + slash(LOCAL_TAGS);
|
||||
myCurrentBookmarkPath = hgDir.getPath() + slash(CURRENT_BOOKMARK);
|
||||
myConfigHgrcPath = hgDir.getPath() + slash(CONFIG_HGRC);
|
||||
}
|
||||
@@ -104,4 +110,12 @@ public class HgRepositoryFiles {
|
||||
public boolean isConfigHgrcFile(String filePath) {
|
||||
return filePath.equals(myConfigHgrcPath);
|
||||
}
|
||||
|
||||
public boolean isTagsFile(String filePath) {
|
||||
return filePath.equals(myTagsPath);
|
||||
}
|
||||
|
||||
public boolean isLocalTagsFile(String filePath) {
|
||||
return filePath.equals(myLocalTagsPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +75,13 @@ public class HgRepositoryImpl extends RepositoryImpl implements HgRepository {
|
||||
return myHgDir;
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public State getState() {
|
||||
return myInfo.getState();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getCurrentBranch() {
|
||||
@@ -105,6 +112,18 @@ public class HgRepositoryImpl extends RepositoryImpl implements HgRepository {
|
||||
return myInfo.getCurrentBookmark();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<HgNameWithHashInfo> getTags() {
|
||||
return myInfo.getTags();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<HgNameWithHashInfo> getLocalTags() {
|
||||
return myInfo.getLocalTags();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public HgConfig getRepositoryConfig() {
|
||||
@@ -142,7 +161,7 @@ public class HgRepositoryImpl extends RepositoryImpl implements HgRepository {
|
||||
//in GitRepositoryImpl there are temporary state object for reader fields storing! Todo Check;
|
||||
return
|
||||
new HgRepoInfo(myReader.readCurrentBranch(), myReader.readCurrentRevision(), myReader.readState(), myReader.readBranches(),
|
||||
myReader.readBookmarks(), myReader.readCurrentBookmark());
|
||||
myReader.readBookmarks(), myReader.readCurrentBookmark(), myReader.readTags(), myReader.readLocalTags());
|
||||
}
|
||||
|
||||
public void updateConfig() {
|
||||
|
||||
@@ -45,6 +45,8 @@ public class HgRepositoryReader {
|
||||
@NotNull private final File myCurrentBranch; // .hg/branch
|
||||
@NotNull private final File myBookmarksFile; //.hg/bookmarks
|
||||
@NotNull private final File myCurrentBookmark; //.hg/bookmarks.current
|
||||
@NotNull private final File myTagsFile; //.hgtags - not in .hg directory!!!
|
||||
@NotNull private final File myLocalTagsFile; // .hg/localtags
|
||||
@NotNull private final VcsLogObjectsFactory myVcsObjectsFactory;
|
||||
|
||||
public HgRepositoryReader(@NotNull File hgDir) {
|
||||
@@ -56,6 +58,8 @@ public class HgRepositoryReader {
|
||||
myCurrentBranch = new File(myHgDir, "branch");
|
||||
myBookmarksFile = new File(myHgDir, "bookmarks");
|
||||
myCurrentBookmark = new File(myHgDir, "bookmarks.current");
|
||||
myLocalTagsFile = new File(myHgDir, "localtags");
|
||||
myTagsFile = new File(myHgDir.getParentFile(), ".hgtags");
|
||||
myVcsObjectsFactory = ServiceManager.getService(VcsLogObjectsFactory.class);
|
||||
}
|
||||
|
||||
@@ -123,19 +127,34 @@ public class HgRepositoryReader {
|
||||
|
||||
@NotNull
|
||||
public Collection<HgNameWithHashInfo> readBookmarks() {
|
||||
// .hg/bookmarks contains hash + name, f.e. 25e44c95b2612e3cdf29a704dabf82c77066cb67 A_BookMark
|
||||
Set<HgNameWithHashInfo> bookmarks = new HashSet<HgNameWithHashInfo>();
|
||||
if (!myBookmarksFile.exists()) {
|
||||
return bookmarks;
|
||||
return readReference(myBookmarksFile);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<HgNameWithHashInfo> readTags() {
|
||||
return readReference(myTagsFile);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<HgNameWithHashInfo> readLocalTags() {
|
||||
return readReference(myLocalTagsFile);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Collection<HgNameWithHashInfo> readReference(@NotNull File fileWithReferences) {
|
||||
// files like .hg/bookmarks which contains hash + name, f.e. 25e44c95b2612e3cdf29a704dabf82c77066cb67 A_BookMark
|
||||
Set<HgNameWithHashInfo> refs = new HashSet<HgNameWithHashInfo>();
|
||||
if (!fileWithReferences.exists()) {
|
||||
return refs;
|
||||
}
|
||||
String[] bookmarksWithHeads = RepositoryUtil.tryLoadFile(myBookmarksFile).split("\n");
|
||||
for (String str : bookmarksWithHeads) {
|
||||
String[] namesWithHashes = RepositoryUtil.tryLoadFile(fileWithReferences).split("\n");
|
||||
for (String str : namesWithHashes) {
|
||||
Matcher matcher = HASH_NAME.matcher(str);
|
||||
if (matcher.matches()) {
|
||||
bookmarks.add(new HgNameWithHashInfo(matcher.group(2), myVcsObjectsFactory.createHash(matcher.group(1))));
|
||||
refs.add(new HgNameWithHashInfo(matcher.group(2), myVcsObjectsFactory.createHash(matcher.group(1))));
|
||||
}
|
||||
}
|
||||
return bookmarks;
|
||||
return refs;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -92,6 +92,8 @@ final class HgRepositoryUpdater implements Disposable, BulkFileListener {
|
||||
boolean branchFileChanged = false;
|
||||
boolean mergeFileChanged = false;
|
||||
boolean bookmarksFileChanged = false;
|
||||
boolean tagsFileChanged = false;
|
||||
boolean localTagsFileChanged = false;
|
||||
boolean currentBookmarkFileChanged = false;
|
||||
boolean configHgrcChanged = false;
|
||||
for (VFileEvent event : events) {
|
||||
@@ -112,6 +114,12 @@ final class HgRepositoryUpdater implements Disposable, BulkFileListener {
|
||||
else if (myRepositoryFiles.isBookmarksFile(filePath)) {
|
||||
bookmarksFileChanged = true;
|
||||
}
|
||||
else if (myRepositoryFiles.isTagsFile(filePath)) {
|
||||
tagsFileChanged = true;
|
||||
}
|
||||
else if (myRepositoryFiles.isLocalTagsFile(filePath)) {
|
||||
localTagsFileChanged = true;
|
||||
}
|
||||
else if (myRepositoryFiles.isCurrentBookmarksFile(filePath)) {
|
||||
currentBookmarkFileChanged = true;
|
||||
}
|
||||
@@ -121,7 +129,13 @@ final class HgRepositoryUpdater implements Disposable, BulkFileListener {
|
||||
}
|
||||
}
|
||||
|
||||
if (branchHeadsChanged || branchFileChanged || mergeFileChanged || bookmarksFileChanged || currentBookmarkFileChanged) {
|
||||
if (branchHeadsChanged ||
|
||||
branchFileChanged ||
|
||||
mergeFileChanged ||
|
||||
bookmarksFileChanged ||
|
||||
currentBookmarkFileChanged ||
|
||||
tagsFileChanged ||
|
||||
localTagsFileChanged) {
|
||||
myUpdateQueue.add(Void.TYPE);
|
||||
}
|
||||
if (configHgrcChanged) {
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
25e44c95b2612e3cdf29a704dabf82c77066cb67 tag1
|
||||
c4e6b94abdf018515b2300698e3eb9b441d53619 tag2
|
||||
@@ -0,0 +1 @@
|
||||
25e44c95b2612e3cdf29a704dabf82c77066cb67 localTag
|
||||
@@ -40,7 +40,7 @@ public class HgRealRepositoryReaderTest extends HgPlatformTest {
|
||||
super.setUp();
|
||||
File hgDir = new File(myRepository.getPath(), ".hg");
|
||||
assertTrue(hgDir.exists());
|
||||
createBranches();
|
||||
createBranchesAndTags();
|
||||
myRepositoryReader = new HgRepositoryReader(hgDir);
|
||||
}
|
||||
|
||||
@@ -62,6 +62,16 @@ public class HgRealRepositoryReaderTest extends HgPlatformTest {
|
||||
Arrays.asList("default", "branchA", "branchB"));
|
||||
}
|
||||
|
||||
public void testTags() {
|
||||
TestRepositoryUtil.assertEqualCollections(HgUtil.getNamesWithoutHashes(myRepositoryReader.readTags()),
|
||||
Arrays.asList("tag1", "tag2"));
|
||||
}
|
||||
|
||||
public void testLocalTags() {
|
||||
TestRepositoryUtil.assertEqualCollections(HgUtil.getNamesWithoutHashes(myRepositoryReader.readLocalTags()),
|
||||
Arrays.asList("localTag"));
|
||||
}
|
||||
|
||||
public void testCurrentBookmark() {
|
||||
hg("update B_BookMark");
|
||||
assertEquals(myRepositoryReader.readCurrentBookmark(), "B_BookMark");
|
||||
@@ -72,19 +82,22 @@ public class HgRealRepositoryReaderTest extends HgPlatformTest {
|
||||
Arrays.asList("A_BookMark", "B_BookMark", "C_BookMark"));
|
||||
}
|
||||
|
||||
private void createBranches() {
|
||||
private void createBranchesAndTags() {
|
||||
cd(myRepository);
|
||||
hg("bookmark A_BookMark");
|
||||
hg("tag tag1");
|
||||
String aFile = "A.txt";
|
||||
touch(aFile, "base");
|
||||
hg("add " + aFile);
|
||||
hg("commit -m 'create file'");
|
||||
hg("bookmark B_BookMark");
|
||||
hg("branch branchA");
|
||||
hg("tag tag2");
|
||||
echo(aFile, " modify with a");
|
||||
hg("commit -m 'create branchA'");
|
||||
hg("up default");
|
||||
hg("branch branchB");
|
||||
hg("tag -l localTag");
|
||||
echo(aFile, " modify with b");
|
||||
hg("commit -m 'modify file in branchB'");
|
||||
hg("bookmark C_BookMark");
|
||||
|
||||
@@ -37,6 +37,8 @@ public class HgRepositoryReaderTest extends HgPlatformTest {
|
||||
@NotNull private File myHgDir;
|
||||
@NotNull private Collection<String> myBranches;
|
||||
@NotNull private Collection<String> myBookmarks;
|
||||
@NotNull private Collection<String> myTags;
|
||||
@NotNull private Collection<String> myLocalTags;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
@@ -52,14 +54,20 @@ public class HgRepositoryReaderTest extends HgPlatformTest {
|
||||
File testBranchFile = new File(testHgDir, "branch");
|
||||
File testBookmarkFile = new File(testHgDir, "bookmarks");
|
||||
File testCurrentBookmarkFile = new File(testHgDir, "bookmarks.current");
|
||||
File testTagFile = new File(testHgDir.getParentFile(), ".hgtags");
|
||||
File testLocalTagFile = new File(testHgDir, "localtags");
|
||||
FileUtil.copyDir(cacheDir, new File(myHgDir, "cache"));
|
||||
FileUtil.copy(testBranchFile, new File(myHgDir, "branch"));
|
||||
FileUtil.copy(testBookmarkFile, new File(myHgDir, "bookmarks"));
|
||||
FileUtil.copy(testCurrentBookmarkFile, new File(myHgDir, "bookmarks.current"));
|
||||
FileUtil.copy(testTagFile, new File(myHgDir.getParentFile(), ".hgtags"));
|
||||
FileUtil.copy(testLocalTagFile, new File(myHgDir, "localtags"));
|
||||
|
||||
myRepositoryReader = new HgRepositoryReader(myHgDir);
|
||||
myBranches = readBranches();
|
||||
myBookmarks = readBookmarks();
|
||||
myBookmarks = readRefs(testBookmarkFile);
|
||||
myTags = readRefs(testTagFile);
|
||||
myLocalTags = readRefs(testLocalTagFile);
|
||||
}
|
||||
|
||||
public void testHEAD() {
|
||||
@@ -81,6 +89,16 @@ public class HgRepositoryReaderTest extends HgPlatformTest {
|
||||
TestRepositoryUtil.assertEqualCollections(bookmarks, myBookmarks);
|
||||
}
|
||||
|
||||
public void testTags() {
|
||||
Collection<String> tags = HgUtil.getNamesWithoutHashes(myRepositoryReader.readTags());
|
||||
TestRepositoryUtil.assertEqualCollections(tags, myTags);
|
||||
}
|
||||
|
||||
public void testLocalTags() {
|
||||
Collection<String> localTags = HgUtil.getNamesWithoutHashes(myRepositoryReader.readLocalTags());
|
||||
TestRepositoryUtil.assertEqualCollections(localTags, myLocalTags);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Collection<String> readBranches() throws IOException {
|
||||
Collection<String> branches = new HashSet<String>();
|
||||
@@ -100,15 +118,14 @@ public class HgRepositoryReaderTest extends HgPlatformTest {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Collection<String> readBookmarks() throws IOException {
|
||||
Collection<String> bookmarks = new HashSet<String>();
|
||||
File bookmarksFile = new File(myHgDir, "bookmarks");
|
||||
String[] bookmarksWithHashes = FileUtil.loadFile(bookmarksFile).split("\n");
|
||||
for (String str : bookmarksWithHashes) {
|
||||
private static Collection<String> readRefs(@NotNull File refFile) throws IOException {
|
||||
Collection<String> refs = new HashSet<String>();
|
||||
String[] refsWithHashes = FileUtil.loadFile(refFile).split("\n");
|
||||
for (String str : refsWithHashes) {
|
||||
String[] refAndName = str.trim().split(" ");
|
||||
assertEquals(2, refAndName.length);
|
||||
bookmarks.add(refAndName[1]);
|
||||
refs.add(refAndName[1]);
|
||||
}
|
||||
return bookmarks;
|
||||
return refs;
|
||||
}
|
||||
}
|
||||
|
||||
+7
@@ -27,6 +27,7 @@ import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -79,4 +80,10 @@ public class PyLanguageInjectionSupport extends AbstractLanguageInjectionSupport
|
||||
// with multiple injection text ranges (PY-10691)
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getHelpId() {
|
||||
return "reference.settings.language.injection.generic.python";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -473,6 +473,8 @@
|
||||
<postStartupActivity implementation="com.jetbrains.python.packaging.PyPIPackagesUpdater"/>
|
||||
<postStartupActivity implementation="com.jetbrains.python.testing.PyTestRunnerUpdater"/>
|
||||
|
||||
<macro implementation="com.jetbrains.python.sdk.InterpreterDirectoryMacro"/>
|
||||
|
||||
<!-- User skeletons -->
|
||||
<codeInsight.lineMarkerProvider language="Python" implementationClass="com.jetbrains.python.codeInsight.userSkeletons.PyUserSkeletonsLineMarkerProvider"/>
|
||||
|
||||
@@ -504,7 +506,6 @@
|
||||
<!-- Packaging -->
|
||||
<moduleService serviceInterface="com.jetbrains.python.packaging.PyPackageRequirementsSettings"
|
||||
serviceImplementation="com.jetbrains.python.packaging.PyPackageRequirementsSettings"/>
|
||||
|
||||
</extensions>
|
||||
|
||||
<extensionPoints>
|
||||
@@ -547,6 +548,7 @@
|
||||
<dumbAnnotator implementation="com.jetbrains.python.validation.DocStringAnnotator"/>
|
||||
<dumbAnnotator implementation="com.jetbrains.python.validation.PyDefinitionsAnnotator"/>
|
||||
<dumbAnnotator implementation="com.jetbrains.python.validation.GeneratorInArgumentListAnnotator"/>
|
||||
<dumbAnnotator implementation="com.jetbrains.python.validation.StarAnnotator"/>
|
||||
|
||||
<customTargetExpressionStubType implementation="com.jetbrains.python.psi.impl.stubs.PropertyStubType"/>
|
||||
<dialectsTokenSetContributor implementation="com.jetbrains.python.PythonTokenSetContributor"/>
|
||||
|
||||
@@ -85,6 +85,9 @@ public class PyImportOptimizer implements ImportOptimizer {
|
||||
}
|
||||
LanguageLevel langLevel = LanguageLevel.forElement(myFile);
|
||||
for (PyImportStatementBase importStatement : myImportBlock) {
|
||||
if (importStatement instanceof PyFromImportStatement && ((PyFromImportStatement)importStatement).isFromFuture()) {
|
||||
continue;
|
||||
}
|
||||
if (importStatement instanceof PyImportStatement && importStatement.getImportElements().length > 1) {
|
||||
for (PyImportElement importElement : importStatement.getImportElements()) {
|
||||
myMissorted = true;
|
||||
@@ -96,7 +99,7 @@ public class PyImportOptimizer implements ImportOptimizer {
|
||||
else {
|
||||
PsiElement toImport;
|
||||
if (importStatement instanceof PyFromImportStatement) {
|
||||
toImport = ((PyFromImportStatement) importStatement).resolveImportSource();
|
||||
toImport = ((PyFromImportStatement)importStatement).resolveImportSource();
|
||||
}
|
||||
else {
|
||||
toImport = importStatement.getImportElements()[0].resolve();
|
||||
@@ -140,12 +143,21 @@ public class PyImportOptimizer implements ImportOptimizer {
|
||||
addImports(myThirdPartyImports);
|
||||
addImports(myProjectImports);
|
||||
PsiElement lastElement = myImportBlock.get(myImportBlock.size()-1);
|
||||
myFile.deleteChildRange(myImportBlock.get(0), lastElement);
|
||||
myFile.deleteChildRange(findFirstNonFutureImport(), lastElement);
|
||||
for (PyImportStatementBase anImport : myBuiltinImports) {
|
||||
anImport.putCopyableUserData(PyBlock.IMPORT_GROUP_BEGIN, null);
|
||||
}
|
||||
}
|
||||
|
||||
private PyImportStatementBase findFirstNonFutureImport() {
|
||||
for (PyImportStatementBase importStatement: myImportBlock) {
|
||||
if (!(importStatement instanceof PyFromImportStatement && ((PyFromImportStatement)importStatement).isFromFuture())) {
|
||||
return importStatement;
|
||||
}
|
||||
}
|
||||
return myImportBlock.get(0);
|
||||
}
|
||||
|
||||
private static void markGroupBegin(List<PyImportStatementBase> imports) {
|
||||
if (imports.size() > 0) {
|
||||
imports.get(0).putCopyableUserData(PyBlock.IMPORT_GROUP_BEGIN, true);
|
||||
@@ -154,7 +166,7 @@ public class PyImportOptimizer implements ImportOptimizer {
|
||||
|
||||
private void addImports(final List<PyImportStatementBase> imports) {
|
||||
for (PyImportStatementBase newImport: imports) {
|
||||
myFile.addBefore(newImport, myImportBlock.get(0));
|
||||
myFile.addBefore(newImport, findFirstNonFutureImport());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.jetbrains.python.inspections;
|
||||
|
||||
import com.intellij.codeInspection.LocalInspectionToolSession;
|
||||
import com.intellij.codeInspection.ProblemHighlightType;
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
@@ -138,7 +139,7 @@ public class PyArgumentListInspection extends PyInspection {
|
||||
holder.registerProblem(arg, PyBundle.message("INSP.duplicate.star.arg"));
|
||||
}
|
||||
if (flags.contains(CallArgumentsMapping.ArgFlag.IS_POS_PAST_KWD)) {
|
||||
holder.registerProblem(arg, PyBundle.message("INSP.cannot.appear.past.keyword.arg"));
|
||||
holder.registerProblem(arg, PyBundle.message("INSP.cannot.appear.past.keyword.arg"), ProblemHighlightType.ERROR);
|
||||
}
|
||||
if (flags.contains(CallArgumentsMapping.ArgFlag.IS_UNMAPPED)) {
|
||||
holder.registerProblem(arg, PyBundle.message("INSP.unexpected.arg"));
|
||||
|
||||
@@ -835,7 +835,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
}
|
||||
|
||||
private void addCreateClassFix(String refText, PsiElement element, List<LocalQuickFix> actions) {
|
||||
if (refText.length() > 2 && Character.isUpperCase(refText.charAt(0)) && !Character.isUpperCase(refText.charAt(1)) &&
|
||||
if (refText.length() > 2 && Character.isUpperCase(refText.charAt(0)) && !refText.toUpperCase().equals(refText) &&
|
||||
PsiTreeUtil.getParentOfType(element, PyImportStatementBase.class) == null) {
|
||||
PsiElement anchor = element;
|
||||
if (element instanceof PyQualifiedExpression) {
|
||||
|
||||
+10
-5
@@ -21,14 +21,13 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.documentation.DocStringUtil;
|
||||
import com.jetbrains.python.psi.PyFile;
|
||||
import com.jetbrains.python.psi.PyStringLiteralExpression;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* Author: Alexey.Ivanov
|
||||
* Date: 24.03.2010
|
||||
* Time: 20:15:23
|
||||
* @author Alexey.Ivanov
|
||||
*/
|
||||
public class MoveFromFutureImportQuickFix implements LocalQuickFix {
|
||||
@NotNull
|
||||
@@ -46,7 +45,13 @@ public class MoveFromFutureImportQuickFix implements LocalQuickFix {
|
||||
PsiFile psiFile = problemElement.getContainingFile();
|
||||
if (psiFile instanceof PyFile) {
|
||||
PyFile file = (PyFile)psiFile;
|
||||
file.addBefore(problemElement, file.getStatements().get(0));
|
||||
PyStringLiteralExpression docString = DocStringUtil.findDocStringExpression(file);
|
||||
if (docString != null) {
|
||||
file.addAfter(problemElement, docString.getParent() /* PyExpressionStatement */);
|
||||
}
|
||||
else {
|
||||
file.addBefore(problemElement, file.getStatements().get(0));
|
||||
}
|
||||
problemElement.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,6 +221,7 @@ public class PyStringLiteralLexer extends LexerBase {
|
||||
if (myBuffer.charAt(i) == '\\') {
|
||||
LOG.assertTrue(myState == AFTER_FIRST_QUOTE);
|
||||
i++;
|
||||
if (myIsRaw) return i;
|
||||
if (i == myBufferEnd) {
|
||||
myState = AFTER_LAST_QUOTE;
|
||||
return i;
|
||||
@@ -282,7 +283,7 @@ public class PyStringLiteralLexer extends LexerBase {
|
||||
final int quote_limit = myIsTriple ? 3 : 1;
|
||||
int qcnt = 0; // count consequent quotes
|
||||
while (i < myBufferEnd) { // scan to next \something
|
||||
if (myBuffer.charAt(i) == '\\') {
|
||||
if (myBuffer.charAt(i) == '\\' && !myIsRaw) {
|
||||
return i;
|
||||
}
|
||||
if (myState == BEFORE_FIRST_QUOTE && myBuffer.charAt(i) == myQuoteChar) {
|
||||
@@ -292,7 +293,7 @@ public class PyStringLiteralLexer extends LexerBase {
|
||||
qcnt = 0; // for last quote detection in the same pass
|
||||
}
|
||||
}
|
||||
else if (myState == AFTER_FIRST_QUOTE && myBuffer.charAt(i) == myQuoteChar) { // done?
|
||||
else if (myState == AFTER_FIRST_QUOTE && myBuffer.charAt(i) == myQuoteChar && (!myIsRaw || myBuffer.charAt(i-1) != '\\')) { // done?
|
||||
qcnt += 1;
|
||||
if (qcnt == quote_limit) {
|
||||
myState = AFTER_LAST_QUOTE;
|
||||
|
||||
@@ -772,6 +772,7 @@ public class ExpressionParsing extends Parsing {
|
||||
PsiBuilder.Marker starExpr = myBuilder.mark();
|
||||
nextToken();
|
||||
if (!parseBitwiseORExpression(isTargetExpression)) {
|
||||
myBuilder.error(message("PARSE.expected.expression"));
|
||||
starExpr.drop();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -65,29 +65,9 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
|
||||
public void mapArguments(PyCallExpression.PyMarkedCallee resolved_callee, @NotNull TypeEvalContext context) {
|
||||
PyExpression[] arguments = myArgumentList.getArguments();
|
||||
myMarkedCallee = resolved_callee;
|
||||
List<PyExpression> unmatched_args = new LinkedList<PyExpression>();
|
||||
Collections.addAll(unmatched_args, arguments);
|
||||
final List<PyExpression> unmatched_subargs = new LinkedList<PyExpression>(); // unmatched nested arguments will go here
|
||||
// detect starred args
|
||||
for (PyExpression arg : arguments) {
|
||||
if (arg instanceof PyStarArgument) {
|
||||
PyStarArgument star_arg = (PyStarArgument)arg;
|
||||
if (star_arg.isKeyword()) {
|
||||
if (myKwdArg == null) myKwdArg = star_arg;
|
||||
else {
|
||||
markArgument(arg, ArgFlag.IS_DUP_KWD);
|
||||
unmatched_args.remove(arg);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (myTupleArg == null) myTupleArg = star_arg;
|
||||
else {
|
||||
markArgument(arg, ArgFlag.IS_DUP_TUPLE);
|
||||
unmatched_args.remove(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
List<PyExpression> unmatched_args = verifyArguments();
|
||||
|
||||
final List<PyParameter> parameters = PyUtil.getParameters(myMarkedCallee.getCallable(), context);
|
||||
// prepare parameter slots
|
||||
Map<PyNamedParameter, PyExpression> slots = new LinkedHashMap<PyNamedParameter, PyExpression>();
|
||||
@@ -180,15 +160,8 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
|
||||
for (PyExpression arg : unmatched_subargs) {
|
||||
markArgument(arg, ArgFlag.IS_UNMAPPED);
|
||||
}
|
||||
// mark past-bound positional args
|
||||
i = positional_bound;
|
||||
while (i<arguments.length) {
|
||||
PyExpression arg = arguments[i];
|
||||
if (!(arg instanceof PyStarArgument) && !(arg instanceof PyKeywordArgument)) {
|
||||
markArgument(arg, ArgFlag.IS_POS_PAST_KWD);
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
|
||||
boolean seen_named_args = false;
|
||||
// map named args to named params if possible
|
||||
Map<String, PyNamedParameter> parameter_by_name = new LinkedHashMap<String, PyNamedParameter>();
|
||||
@@ -352,6 +325,57 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
|
||||
}
|
||||
}
|
||||
|
||||
public List<PyExpression> verifyArguments() {
|
||||
List<PyExpression> unmatched_args = new LinkedList<PyExpression>();
|
||||
Collections.addAll(unmatched_args, myArgumentList.getArguments());
|
||||
// detect starred args
|
||||
for (PyExpression arg : myArgumentList.getArguments()) {
|
||||
if (arg instanceof PyStarArgument) {
|
||||
PyStarArgument star_arg = (PyStarArgument)arg;
|
||||
if (star_arg.isKeyword()) {
|
||||
if (myKwdArg == null) myKwdArg = star_arg;
|
||||
else {
|
||||
markArgument(arg, ArgFlag.IS_DUP_KWD);
|
||||
unmatched_args.remove(arg);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (myTupleArg == null) myTupleArg = star_arg;
|
||||
else {
|
||||
markArgument(arg, ArgFlag.IS_DUP_TUPLE);
|
||||
unmatched_args.remove(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
markPastBoundPositionalArguments(myArgumentList.getArguments());
|
||||
return unmatched_args;
|
||||
}
|
||||
|
||||
private void markPastBoundPositionalArguments(PyExpression[] arguments) {
|
||||
boolean seenKwArg = false;
|
||||
boolean seenKeyword = false;
|
||||
boolean seenStar = false;
|
||||
for (PyExpression arg : arguments) {
|
||||
if (arg == myKwdArg) {
|
||||
seenKwArg = true;
|
||||
}
|
||||
else if (arg instanceof PyKeywordArgument) {
|
||||
seenKeyword = true;
|
||||
}
|
||||
else if (arg instanceof PyStarArgument) {
|
||||
seenStar = true;
|
||||
}
|
||||
|
||||
if (seenKeyword || seenKwArg || seenStar) {
|
||||
if (!(arg instanceof PyStarArgument) && (seenKwArg || !(arg instanceof PyKeywordArgument))) {
|
||||
markArgument(arg, ArgFlag.IS_POS_PAST_KWD);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isPositionalArg(PyExpression arg) {
|
||||
return !(arg instanceof PyKeywordArgument) && !(arg instanceof PyStarArgument);
|
||||
}
|
||||
|
||||
@@ -269,8 +269,13 @@ public class PyArgumentListImpl extends PyElementImpl implements PyArgumentList
|
||||
// following the spec: http://docs.python.org/ref/calls.html
|
||||
PyCallExpression call = getCallExpression();
|
||||
if (call != null) {
|
||||
PyCallExpression.PyMarkedCallee resolved_callee = call.resolveCallee(resolveContext, offset);
|
||||
if (resolved_callee != null) ret.mapArguments(resolved_callee, resolveContext.getTypeEvalContext());
|
||||
PyCallExpression.PyMarkedCallee resolvedCallee = call.resolveCallee(resolveContext, offset);
|
||||
if (resolvedCallee != null) {
|
||||
ret.mapArguments(resolvedCallee, resolveContext.getTypeEvalContext());
|
||||
}
|
||||
else {
|
||||
ret.verifyArguments();
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jetbrains.python.sdk;
|
||||
|
||||
import com.intellij.ide.macro.Macro;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.PathUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class InterpreterDirectoryMacro extends Macro {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "PyInterpreterDirectory";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "The directory containing the Python interpreter selected for the project";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String expand(DataContext dataContext) throws ExecutionCancelledException {
|
||||
Module module = LangDataKeys.MODULE.getData(dataContext);
|
||||
if (module == null) {
|
||||
Project project = CommonDataKeys.PROJECT.getData(dataContext);
|
||||
if (project == null) {
|
||||
return null;
|
||||
}
|
||||
Module[] modules = ModuleManager.getInstance(project).getModules();
|
||||
if (modules.length == 0) {
|
||||
return null;
|
||||
}
|
||||
module = modules[0];
|
||||
}
|
||||
Sdk sdk = PythonSdkType.findPythonSdk(module);
|
||||
if (sdk != null) {
|
||||
VirtualFile homeDir = sdk.getHomeDirectory();
|
||||
if (homeDir == null) {
|
||||
return null;
|
||||
}
|
||||
String path = PathUtil.getLocalPath(homeDir.getParent());
|
||||
if (path != null) {
|
||||
return FileUtil.toSystemDependentName(path);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,6 @@ import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationListener;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
@@ -556,16 +555,22 @@ public class PythonSdkType extends SdkType {
|
||||
|
||||
@NotNull
|
||||
public static Notification createInvalidSdkNotification(@Nullable final Project project) {
|
||||
String message = "Cannot run the project interpreter.";
|
||||
if (project != null && !project.isDisposed()) {
|
||||
message += " <a href=\"xxx\">Configure...</a>";
|
||||
}
|
||||
return new Notification("xxx",
|
||||
"Invalid Project Interpreter",
|
||||
"Cannot run the project interpreter. <a href=\"xxx\">Configure...</a>",
|
||||
message,
|
||||
NotificationType.ERROR,
|
||||
new NotificationListener() {
|
||||
@Override
|
||||
public void hyperlinkUpdate(@NotNull Notification notification,
|
||||
@NotNull HyperlinkEvent event) {
|
||||
final ShowSettingsUtil settings = ShowSettingsUtil.getInstance();
|
||||
settings.showSettingsDialog(project, "Project Interpreter");
|
||||
if (project != null && !project.isDisposed()) {
|
||||
final ShowSettingsUtil settings = ShowSettingsUtil.getInstance();
|
||||
settings.showSettingsDialog(project, "Project Interpreter");
|
||||
}
|
||||
notification.expire();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jetbrains.python.validation;
|
||||
|
||||
import com.jetbrains.python.psi.PyStarExpression;
|
||||
import com.jetbrains.python.psi.PyTargetExpression;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class StarAnnotator extends PyAnnotator {
|
||||
@Override
|
||||
public void visitPyStarExpression(PyStarExpression node) {
|
||||
super.visitPyStarExpression(node);
|
||||
if (!(node.getExpression() instanceof PyTargetExpression)) {
|
||||
getHolder().createErrorAnnotation(node, "can use starred expression only as assignment target");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
y = (<error descr="can use starred expression only as assignment target">*()</error> for _ in ())
|
||||
@@ -0,0 +1,10 @@
|
||||
"""This is a docstring."""
|
||||
|
||||
from __future__ import print_function
|
||||
#comment
|
||||
from __future__ import absolute_import
|
||||
|
||||
class A:
|
||||
pass
|
||||
|
||||
<warning descr="from __future__ imports must occur at the beginning of the file"><caret>from __future__ import with_statement</warning>
|
||||
@@ -0,0 +1,10 @@
|
||||
"""This is a docstring."""
|
||||
from __future__ import with_statement
|
||||
|
||||
from __future__ import print_function
|
||||
#comment
|
||||
from __future__ import absolute_import
|
||||
|
||||
class A:
|
||||
pass
|
||||
|
||||
@@ -42,7 +42,7 @@ f3(1, 2, <warning descr="Unexpected argument">3</warning>)
|
||||
f3(b=2, a=1)
|
||||
f3(b=1, <warning descr="Duplicate argument">b=2</warning>, a=1)
|
||||
f3(1, b=2)
|
||||
f3(a=1, <warning descr="Cannot appear past keyword arguments or *arg or **kwarg">2</warning><warning descr="Parameter 'b' unfilled">)</warning>
|
||||
f3(a=1, <error descr="Cannot appear past keyword arguments or *arg or **kwarg">2</error><warning descr="Parameter 'b' unfilled">)</warning>
|
||||
|
||||
def f4(a, *b):
|
||||
pass
|
||||
@@ -52,4 +52,4 @@ f4(1, 2)
|
||||
f4(1, 2, 3)
|
||||
f4(1, *(2, 3))
|
||||
f4(*(1,2,3))
|
||||
f4(a=1, <warning descr="Cannot appear past keyword arguments or *arg or **kwarg">2</warning>, <warning descr="Cannot appear past keyword arguments or *arg or **kwarg">3</warning>)
|
||||
f4(a=1, <error descr="Cannot appear past keyword arguments or *arg or **kwarg">2</error>, <error descr="Cannot appear past keyword arguments or *arg or **kwarg">3</error>)
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
def foo(**kwargs): pass
|
||||
|
||||
two = 0
|
||||
kw = {}
|
||||
foo(**kw, <error descr="Cannot appear past keyword arguments or *arg or **kwarg">two=1</error>)
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
kwargs = {'foo': 'bar'}
|
||||
|
||||
|
||||
class Foo(object):
|
||||
|
||||
@classmethod
|
||||
def test(cls):
|
||||
cls(**kwargs, <error descr="Cannot appear past keyword arguments or *arg or **kwarg">foo=1</error>)
|
||||
@@ -19,7 +19,7 @@ def f2(a, b, c=1, *d):
|
||||
f2(c=3, *(1,2))
|
||||
f2(1,2,3, *(1,2))
|
||||
f2(*(1,2), c=20)
|
||||
f2(*(1,2), <warning descr="Cannot appear past keyword arguments or *arg or **kwarg">20</warning>) # fail: positional past *
|
||||
f2(*(1,2), <error descr="Cannot appear past keyword arguments or *arg or **kwarg">20</error>) # fail: positional past *
|
||||
|
||||
def f3(a=1, b=2, c=3, *d):
|
||||
return a,b,c,d
|
||||
|
||||
@@ -13,7 +13,7 @@ namedpast(1,2,3, foo='a') # pass
|
||||
namedpast(*args, foo='b') # pass
|
||||
namedpast(foo='c') # pass
|
||||
namedpast() # pass
|
||||
namedpast(foo='1', <warning descr="Cannot appear past keyword arguments or *arg or **kwarg">2</warning>) # fail
|
||||
namedpast(foo='1', <error descr="Cannot appear past keyword arguments or *arg or **kwarg">2</error>) # fail
|
||||
|
||||
def a23(a, *b, c=1):
|
||||
pass
|
||||
@@ -21,7 +21,7 @@ def a23(a, *b, c=1):
|
||||
a23(1,2,3, c=10) # pass
|
||||
a23(1,2,3, c=10, <warning descr="Duplicate argument">a=1</warning>) # fail
|
||||
a23(c=10, a=1) # pass
|
||||
a23(c=10, <warning descr="Cannot appear past keyword arguments or *arg or **kwarg">1</warning><warning descr="Parameter 'a' unfilled">)</warning> # fail
|
||||
a23(c=10, <error descr="Cannot appear past keyword arguments or *arg or **kwarg">1</error><warning descr="Parameter 'a' unfilled">)</warning> # fail
|
||||
a23(<warning descr="Multiple values resolve to positional parameter 'a'">*args</warning>, a=1) # fail
|
||||
a23(*args, c=1) # pass
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from __future__ import with_statement
|
||||
import sys
|
||||
import datetime
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from __future__ import with_statement
|
||||
import foo
|
||||
import sys
|
||||
from bar import *
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
x = (*)
|
||||
@@ -0,0 +1,13 @@
|
||||
PyFile:LoneStar.py
|
||||
PyAssignmentStatement
|
||||
PyTargetExpression: x
|
||||
PsiElement(Py:IDENTIFIER)('x')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyParenthesizedExpression
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:MULT)('*')
|
||||
PsiErrorElement:expression expected
|
||||
<empty list>
|
||||
PsiElement(Py:RPAR)(')')
|
||||
@@ -0,0 +1 @@
|
||||
s = r'Hello\<selection>nWorld</selection>!'
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user