mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch origin/master
This commit is contained in:
+13
-2
@@ -17,12 +17,16 @@ package com.intellij.codeInspection.dataFlow;
|
||||
|
||||
import com.intellij.codeInsight.NullableNotNullManager;
|
||||
import com.intellij.codeInspection.dataFlow.MethodContract.ValueConstraint;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.RecursionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.NullableFunction;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -39,6 +43,7 @@ import static com.intellij.codeInspection.dataFlow.MethodContract.ValueConstrain
|
||||
* @author peter
|
||||
*/
|
||||
public class ContractInference {
|
||||
public static final int MAX_CONTRACT_COUNT = 10;
|
||||
|
||||
@NotNull
|
||||
public static List<MethodContract> inferContracts(@NotNull final PsiMethod method) {
|
||||
@@ -64,6 +69,7 @@ public class ContractInference {
|
||||
}
|
||||
|
||||
class ContractInferenceInterpreter {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.dataFlow.ContractInferenceInterpreter");
|
||||
private final PsiMethod myMethod;
|
||||
private final ValueConstraint[] myEmptyConstraints;
|
||||
|
||||
@@ -84,7 +90,7 @@ class ContractInferenceInterpreter {
|
||||
if (referenceTypeReturned) {
|
||||
contracts = boxReturnValues(contracts);
|
||||
}
|
||||
return ContainerUtil.filter(contracts, new Condition<MethodContract>() {
|
||||
List<MethodContract> compatible = ContainerUtil.filter(contracts, new Condition<MethodContract>() {
|
||||
@Override
|
||||
public boolean value(MethodContract contract) {
|
||||
if (notNull && contract.returnValue == NOT_NULL_VALUE) {
|
||||
@@ -93,6 +99,11 @@ class ContractInferenceInterpreter {
|
||||
return InferenceFromSourceUtil.isReturnTypeCompatible(returnType, contract.returnValue);
|
||||
}
|
||||
});
|
||||
if (compatible.size() > ContractInference.MAX_CONTRACT_COUNT) {
|
||||
LOG.debug("Too many contracts for " + PsiUtil.getMemberQualifiedName(myMethod) + ", shrinking the list");
|
||||
return compatible.subList(0, ContractInference.MAX_CONTRACT_COUNT);
|
||||
}
|
||||
return compatible;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+7
-4
@@ -264,10 +264,8 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
private Integer getOrCreateEqClassIndex(DfaValue dfaValue) {
|
||||
int i = getEqClassIndex(dfaValue);
|
||||
if (i != -1) return i;
|
||||
if (!canBeReused(dfaValue) && !(((DfaBoxedValue)dfaValue).getWrappedValue() instanceof DfaConstValue)) {
|
||||
return null;
|
||||
}
|
||||
if (dfaValue instanceof DfaTypeValue) {
|
||||
if (!canBeInRelation(dfaValue) ||
|
||||
!canBeReused(dfaValue) && !(((DfaBoxedValue)dfaValue).getWrappedValue() instanceof DfaConstValue)) {
|
||||
return null;
|
||||
}
|
||||
EqClass aClass = new EqClass(myFactory);
|
||||
@@ -283,6 +281,11 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
return myEqClasses.size() - 1;
|
||||
}
|
||||
|
||||
private static boolean canBeInRelation(DfaValue dfaValue) {
|
||||
DfaValue unwrapped = unwrap(dfaValue);
|
||||
return unwrapped instanceof DfaVariableValue || unwrapped instanceof DfaConstValue;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
List<DfaValue> getEquivalentValues(@NotNull DfaValue dfaValue) {
|
||||
int index = getEqClassIndex(dfaValue);
|
||||
|
||||
+16
-9
@@ -17,6 +17,7 @@ package com.intellij.codeInspection.dataFlow;
|
||||
|
||||
import com.intellij.codeInspection.dataFlow.instructions.*;
|
||||
import com.intellij.codeInspection.dataFlow.value.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
@@ -29,10 +30,7 @@ import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.psi.JavaTokenType.*;
|
||||
|
||||
@@ -40,6 +38,7 @@ import static com.intellij.psi.JavaTokenType.*;
|
||||
* @author peter
|
||||
*/
|
||||
public class StandardInstructionVisitor extends InstructionVisitor {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.dataFlow.StandardInstructionVisitor");
|
||||
private static final Object ANY_VALUE = new Object();
|
||||
private final Set<BinopInstruction> myReachable = new THashSet<BinopInstruction>();
|
||||
private final Set<BinopInstruction> myCanBeNullInInstanceof = new THashSet<BinopInstruction>();
|
||||
@@ -161,11 +160,19 @@ public class StandardInstructionVisitor extends InstructionVisitor {
|
||||
DfaValue[] argValues = popCallArguments(instruction, runner, memState);
|
||||
final DfaValue qualifier = popQualifier(instruction, runner, memState);
|
||||
|
||||
List<DfaMemoryState> currentStates = ContainerUtil.newArrayList(memState);
|
||||
LinkedHashSet<DfaMemoryState> currentStates = ContainerUtil.newLinkedHashSet(memState);
|
||||
Set<DfaMemoryState> finalStates = ContainerUtil.newLinkedHashSet();
|
||||
if (argValues != null) {
|
||||
for (MethodContract contract : instruction.getContracts()) {
|
||||
currentStates = addContractResults(argValues, contract, currentStates, instruction, runner.getFactory(), finalStates);
|
||||
if (currentStates.size() + finalStates.size() > DataFlowRunner.MAX_STATES_PER_BRANCH) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Too complex contract on " + instruction.getContext() + ", skipping contract processing");
|
||||
}
|
||||
finalStates.clear();
|
||||
currentStates = ContainerUtil.newLinkedHashSet(memState);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (DfaMemoryState state : currentStates) {
|
||||
@@ -237,14 +244,14 @@ public class StandardInstructionVisitor extends InstructionVisitor {
|
||||
return qualifier;
|
||||
}
|
||||
|
||||
private List<DfaMemoryState> addContractResults(DfaValue[] argValues,
|
||||
private LinkedHashSet<DfaMemoryState> addContractResults(DfaValue[] argValues,
|
||||
MethodContract contract,
|
||||
List<DfaMemoryState> states,
|
||||
LinkedHashSet<DfaMemoryState> states,
|
||||
MethodCallInstruction instruction,
|
||||
DfaValueFactory factory,
|
||||
Set<DfaMemoryState> finalStates) {
|
||||
DfaConstValue.Factory constFactory = factory.getConstFactory();
|
||||
List<DfaMemoryState> falseStates = ContainerUtil.newArrayList();
|
||||
LinkedHashSet<DfaMemoryState> falseStates = ContainerUtil.newLinkedHashSet();
|
||||
for (int i = 0; i < argValues.length; i++) {
|
||||
DfaValue argValue = argValues[i];
|
||||
MethodContract.ValueConstraint constraint = contract.arguments[i];
|
||||
@@ -263,7 +270,7 @@ public class StandardInstructionVisitor extends InstructionVisitor {
|
||||
condition = constFactory.createFromValue((argValue == expectedValue) != invertCondition, PsiType.BOOLEAN, null);
|
||||
}
|
||||
|
||||
List<DfaMemoryState> nextStates = ContainerUtil.newArrayList();
|
||||
LinkedHashSet<DfaMemoryState> nextStates = ContainerUtil.newLinkedHashSet();
|
||||
for (DfaMemoryState state : states) {
|
||||
boolean unknownVsNull = expectedValue == constFactory.getNull() &&
|
||||
argValue instanceof DfaVariableValue &&
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,7 +20,6 @@ import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.jsp.jspXml.JspDirective;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.psi.xml.XmlFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class JavaCodeBlockModificationListener implements PsiTreeChangePreprocessor {
|
||||
@@ -70,9 +69,11 @@ public class JavaCodeBlockModificationListener implements PsiTreeChangePreproces
|
||||
private void processChange(final PsiElement parent, final PsiElement child1, final PsiElement child2) {
|
||||
try {
|
||||
if (!isInsideCodeBlock(parent)) {
|
||||
if (parent != null && isClassOwner(parent.getContainingFile()) ||
|
||||
isClassOwner(child1) || isClassOwner(child2) || isSourceDir(parent) ||
|
||||
(parent != null && isClassOwner(parent.getParent()))) {
|
||||
if (isClassOwner(parent.getContainingFile()) ||
|
||||
isClassOwner(child1) ||
|
||||
isClassOwner(child2) ||
|
||||
isSourceDir(parent) ||
|
||||
isClassOwner(parent.getParent())) {
|
||||
myModificationTracker.incCounter();
|
||||
}
|
||||
else {
|
||||
@@ -96,7 +97,7 @@ public class JavaCodeBlockModificationListener implements PsiTreeChangePreproces
|
||||
}
|
||||
|
||||
private static boolean isClassOwner(final PsiElement element) {
|
||||
return element instanceof PsiClassOwner && !(element instanceof XmlFile) || element instanceof JspDirective;
|
||||
return element instanceof PsiClassOwner || element instanceof JspDirective;
|
||||
}
|
||||
|
||||
private static boolean containsClassesInside(final PsiElement element) {
|
||||
|
||||
+2
-2
@@ -19,8 +19,8 @@ import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.NonPhysicalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.ex.dummy.DummyFileSystem;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiElementBase;
|
||||
import com.intellij.psi.search.PsiElementProcessor;
|
||||
@@ -192,7 +192,7 @@ class PackagePrefixFileSystemItemImpl extends PsiElementBase implements PsiFileS
|
||||
@Override
|
||||
public boolean isPhysical() {
|
||||
final VirtualFile file = getVirtualFile();
|
||||
return file != null && !(file.getFileSystem() instanceof DummyFileSystem);
|
||||
return file != null && !(file.getFileSystem() instanceof NonPhysicalFileSystem);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: dsl
|
||||
* Date: 06.05.2002
|
||||
* Time: 14:03:43
|
||||
* To change template for new class use
|
||||
* Code Style | Class Templates options (Tools | IDE Options).
|
||||
*/
|
||||
package com.intellij.refactoring.actions;
|
||||
|
||||
import com.intellij.lang.refactoring.RefactoringSupportProvider;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.refactoring.HelpID;
|
||||
import com.intellij.refactoring.RefactoringActionHandler;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.extractMethod.ExtractMethodHandler;
|
||||
import com.intellij.refactoring.introduceParameter.IntroduceParameterHandler;
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class IntroduceFunctionalParameterAction extends BasePlatformRefactoringAction {
|
||||
private static final String REFACTORING_NAME = RefactoringBundle.message("introduce.functional.parameter.title");
|
||||
|
||||
@Override
|
||||
protected boolean isAvailableInEditorOnly() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabledOnElements(@NotNull PsiElement[] elements) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RefactoringActionHandler getRefactoringHandler(@NotNull RefactoringSupportProvider provider) {
|
||||
return new IntroduceParameterHandler() {
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) {
|
||||
if (dataContext != null) {
|
||||
final PsiFile file = CommonDataKeys.PSI_FILE.getData(dataContext);
|
||||
final Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
|
||||
if (file != null && editor != null && !introduceStrategy(project, editor, file, elements)) {
|
||||
showErrorMessage(project, editor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file, DataContext dataContext) {
|
||||
ExtractMethodHandler.selectAndPass(project, editor, file, new Pass<PsiElement[]>() {
|
||||
@Override
|
||||
public void pass(PsiElement[] elements) {
|
||||
if (!introduceStrategy(project, editor, file, elements)) {
|
||||
showErrorMessage(project, editor);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void showErrorMessage(@NotNull Project project, Editor editor) {
|
||||
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("is.not.supported.in.the.current.context", REFACTORING_NAME));
|
||||
CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INTRODUCE_PARAMETER);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@ public class ElementToWorkOn {
|
||||
public static final Key<String> PREFIX = Key.create("prefix");
|
||||
public static final Key<String> SUFFIX = Key.create("suffix");
|
||||
public static final Key<RangeMarker> TEXT_RANGE = Key.create("range");
|
||||
public static final Key<Boolean> REPLACE_NON_PHYSICAL = Key.create("replace_non_physical");
|
||||
public static final Key<Boolean> OUT_OF_CODE_BLOCK= Key.create("out_of_code_block");
|
||||
|
||||
private ElementToWorkOn(PsiLocalVariable localVariable, PsiExpression expr) {
|
||||
|
||||
+76
-56
@@ -50,7 +50,6 @@ import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Pass;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
@@ -528,68 +527,77 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
|
||||
public boolean introduceStrategy(final Project project, final Editor editor, PsiFile file) {
|
||||
final SelectionModel selectionModel = editor.getSelectionModel();
|
||||
if (selectionModel.hasSelection()) {
|
||||
final PsiElement[] elements = CodeInsightUtil
|
||||
.findStatementsInRange(file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
|
||||
if (elements.length > 0) {
|
||||
final AbstractInplaceIntroducer inplaceIntroducer = AbstractInplaceIntroducer.getActiveIntroducer(editor);
|
||||
if (inplaceIntroducer instanceof InplaceIntroduceParameterPopup) {
|
||||
return false;
|
||||
}
|
||||
final List<PsiMethod> enclosingMethods = getEnclosingMethods(Util.getContainingMethod(elements[0]));
|
||||
if (enclosingMethods.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
final PsiElement[] elements = CodeInsightUtil.findStatementsInRange(file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
|
||||
return introduceStrategy(project, editor, file, elements);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiFile copy = PsiFileFactory.getInstance(project)
|
||||
.createFileFromText(file.getName(), file.getFileType(), file.getText(), file.getModificationStamp(), false);
|
||||
@VisibleForTesting
|
||||
public boolean introduceStrategy(final Project project, final Editor editor, PsiFile file, final PsiElement[] elements) {
|
||||
if (elements.length > 0) {
|
||||
final AbstractInplaceIntroducer inplaceIntroducer = AbstractInplaceIntroducer.getActiveIntroducer(editor);
|
||||
if (inplaceIntroducer instanceof InplaceIntroduceParameterPopup) {
|
||||
return false;
|
||||
}
|
||||
final List<PsiMethod> enclosingMethods = getEnclosingMethods(Util.getContainingMethod(elements[0]));
|
||||
if (enclosingMethods.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiElement[] elementsCopy = CodeInsightUtil.findStatementsInRange(copy,
|
||||
elements[0].getTextRange().getStartOffset(),
|
||||
final PsiFile copy = PsiFileFactory.getInstance(project)
|
||||
.createFileFromText(file.getName(), file.getFileType(), file.getText(), file.getModificationStamp(), false);
|
||||
|
||||
final PsiExpression exprInRange = CodeInsightUtil.findExpressionInRange(copy, elements[0].getTextRange().getStartOffset(),
|
||||
elements[elements.length - 1].getTextRange().getEndOffset());
|
||||
final PsiElement[] elementsCopy = exprInRange != null
|
||||
? new PsiElement[] {exprInRange}
|
||||
: CodeInsightUtil.findStatementsInRange(copy, elements[0].getTextRange().getStartOffset(),
|
||||
elements[elements.length - 1].getTextRange().getEndOffset());
|
||||
final MyExtractMethodProcessor processor = new MyExtractMethodProcessor(project, editor, elementsCopy);
|
||||
try {
|
||||
if (!processor.prepare()) return false;
|
||||
processor.showDialog();
|
||||
final MyExtractMethodProcessor processor = new MyExtractMethodProcessor(project, editor, elementsCopy);
|
||||
try {
|
||||
if (!processor.prepare()) return false;
|
||||
processor.showDialog();
|
||||
|
||||
//provide context for generated method to check exceptions compatibility
|
||||
final PsiMethod emptyMethod = JavaPsiFacade.getElementFactory(project)
|
||||
.createMethodFromText(processor.generateEmptyMethod("name").getText(), elements[0]);
|
||||
final Collection<? extends PsiType> types = FunctionalInterfaceSuggester.suggestFunctionalInterfaces(emptyMethod);
|
||||
if (types.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
//provide context for generated method to check exceptions compatibility
|
||||
final PsiMethod emptyMethod = JavaPsiFacade.getElementFactory(project)
|
||||
.createMethodFromText(processor.generateEmptyMethod("name").getText(), elements[0]);
|
||||
final Collection<? extends PsiType> types = FunctionalInterfaceSuggester.suggestFunctionalInterfaces(emptyMethod);
|
||||
if (types.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (types.size() == 1 || ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
final PsiType next = types.iterator().next();
|
||||
functionalInterfaceSelected(next, enclosingMethods, project, editor, processor, elements);
|
||||
if (types.size() == 1 || ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
final PsiType next = types.iterator().next();
|
||||
functionalInterfaceSelected(next, enclosingMethods, project, editor, processor, elements);
|
||||
}
|
||||
else {
|
||||
final Map<PsiClass, PsiType> classes = new LinkedHashMap<PsiClass, PsiType>();
|
||||
for (PsiType type : types) {
|
||||
classes.put(PsiUtil.resolveClassInType(type), type);
|
||||
}
|
||||
else {
|
||||
final Map<PsiClass, PsiType> classes = new LinkedHashMap<PsiClass, PsiType>();
|
||||
for (PsiType type : types) {
|
||||
classes.put(PsiUtil.resolveClassInType(type), type);
|
||||
}
|
||||
final PsiClass[] psiClasses = classes.keySet().toArray(new PsiClass[classes.size()]);
|
||||
final String methodSignature =
|
||||
PsiFormatUtil.formatMethod(emptyMethod, PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_TYPE);
|
||||
final PsiType returnType = emptyMethod.getReturnType();
|
||||
LOG.assertTrue(returnType != null);
|
||||
final String title = "Choose Applicable Functional Interface: " + methodSignature + " -> " + returnType.getPresentableText();
|
||||
NavigationUtil.getPsiElementPopup(psiClasses, new PsiClassListCellRenderer(), title,
|
||||
new PsiElementProcessor<PsiClass>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiClass psiClass) {
|
||||
functionalInterfaceSelected(classes.get(psiClass), enclosingMethods, project, editor, processor, elements);
|
||||
return true;
|
||||
}
|
||||
}).showInBestPositionFor(editor);
|
||||
return true;
|
||||
}
|
||||
|
||||
final PsiClass[] psiClasses = classes.keySet().toArray(new PsiClass[classes.size()]);
|
||||
final String methodSignature =
|
||||
PsiFormatUtil.formatMethod(emptyMethod, PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_TYPE);
|
||||
final PsiType returnType = emptyMethod.getReturnType();
|
||||
LOG.assertTrue(returnType != null);
|
||||
final String title = "Choose Applicable Functional Interface: " + methodSignature + " -> " + returnType.getPresentableText();
|
||||
NavigationUtil.getPsiElementPopup(psiClasses, new PsiClassListCellRenderer(), title,
|
||||
new PsiElementProcessor<PsiClass>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiClass psiClass) {
|
||||
functionalInterfaceSelected(classes.get(psiClass), enclosingMethods, project, editor, processor,
|
||||
elements);
|
||||
return true;
|
||||
}
|
||||
}).showInBestPositionFor(editor);
|
||||
return true;
|
||||
}
|
||||
catch (IncorrectOperationException ignore) {}
|
||||
catch (PrepareFailedException ignore) {}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (IncorrectOperationException ignore) {}
|
||||
catch (PrepareFailedException ignore) {}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -615,7 +623,8 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
|
||||
final PsiType selectedType,
|
||||
final MyExtractMethodProcessor processor,
|
||||
final PsiElement[] elements) {
|
||||
final PsiElement commonParent = elements.length > 1 ? PsiTreeUtil.findCommonParent(elements) : elements[0].getParent();
|
||||
final PsiElement commonParent = elements.length > 1 ? PsiTreeUtil.findCommonParent(elements)
|
||||
: PsiTreeUtil.getParentOfType(elements[0].getParent(), PsiCodeBlock.class, false);
|
||||
if (commonParent == null) {
|
||||
LOG.error("Should have common parent:" + Arrays.toString(elements));
|
||||
return;
|
||||
@@ -623,7 +632,8 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
|
||||
final RangeMarker marker = editor.getDocument().createRangeMarker(commonParent.getTextRange());
|
||||
|
||||
final PsiElement[] copyElements = processor.getElements();
|
||||
final PsiElement containerCopy = copyElements.length > 1 ? PsiTreeUtil.findCommonParent(copyElements) : copyElements[0].getParent();
|
||||
final PsiElement containerCopy = copyElements.length > 1 ? PsiTreeUtil.findCommonParent(copyElements)
|
||||
: PsiTreeUtil.getParentOfType(copyElements[0].getParent(), PsiCodeBlock.class, false);
|
||||
if (containerCopy == null) {
|
||||
LOG.error("Should have common parent:" + Arrays.toString(copyElements));
|
||||
return;
|
||||
@@ -644,6 +654,11 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
|
||||
LOG.assertTrue(method != null);
|
||||
final String interfaceMethodName = method.getName();
|
||||
processor.setMethodName(interfaceMethodName);
|
||||
|
||||
if (copyElements.length == 1) {
|
||||
copyElements[0].putUserData(ElementToWorkOn.REPLACE_NON_PHYSICAL, true);
|
||||
}
|
||||
|
||||
processor.doExtract();
|
||||
|
||||
final PsiMethod extractedMethod = processor.getExtractedMethod();
|
||||
@@ -704,6 +719,11 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isFoldingApplicable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean prepare(@Nullable Pass<ExtractMethodProcessor> pass) throws PrepareFailedException {
|
||||
final boolean prepare = super.prepare(pass);
|
||||
|
||||
+1
-1
@@ -1000,7 +1000,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
|
||||
} else {
|
||||
expr2 = RefactoringUtil.outermostParenthesizedExpression(expr1);
|
||||
}
|
||||
if (expr2.isPhysical()) {
|
||||
if (expr2.isPhysical() || expr1.getUserData(ElementToWorkOn.REPLACE_NON_PHYSICAL) != null) {
|
||||
return expr2.replace(ref);
|
||||
}
|
||||
else {
|
||||
|
||||
+29
-18
@@ -23,6 +23,7 @@ import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.refactoring.changeSignature.MethodNodeBase;
|
||||
import com.intellij.refactoring.changeSignature.inCallers.JavaCallerChooser;
|
||||
@@ -111,37 +112,47 @@ abstract class SafeDeleteJavaCallerChooser extends JavaCallerChooser {
|
||||
final PsiExpression[] expressions = argumentList.getExpressions();
|
||||
if (expressions.length > parameterIndex) {
|
||||
final PsiExpression expression = PsiUtil.deparenthesizeExpression(expressions[parameterIndex]);
|
||||
if (expression instanceof PsiReferenceExpression) {
|
||||
final PsiElement resolve = ((PsiReferenceExpression)expression).resolve();
|
||||
if (resolve instanceof PsiParameter && !((PsiParameter)resolve).isVarArgs()) {
|
||||
final PsiElement scope = ((PsiParameter)resolve).getDeclarationScope();
|
||||
if (expression != null) {
|
||||
final Set<PsiParameter> paramRefs = new HashSet<PsiParameter>();
|
||||
expression.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
super.visitReferenceExpression(expression);
|
||||
final PsiElement resolve = expression.resolve();
|
||||
if (resolve instanceof PsiParameter) {
|
||||
paramRefs.add((PsiParameter)resolve);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final PsiParameter parameter = ContainerUtil.getFirstItem(paramRefs);
|
||||
if (parameter != null && !parameter.isVarArgs()) {
|
||||
final PsiElement scope = parameter.getDeclarationScope();
|
||||
if (scope instanceof PsiMethod && ((PsiMethod)scope).findDeepestSuperMethods().length == 0) {
|
||||
final Ref<Boolean> ref = new Ref<Boolean>(false);
|
||||
if (ReferencesSearch.search(resolve, new LocalSearchScope(scope)).forEach(new Processor<PsiReference>() {
|
||||
if (ReferencesSearch.search(parameter, new LocalSearchScope(scope)).forEach(new Processor<PsiReference>() {
|
||||
@Override
|
||||
public boolean process(PsiReference reference) {
|
||||
final PsiElement element = reference.getElement();
|
||||
if (element instanceof PsiReferenceExpression) {
|
||||
final PsiElement parent = element.getParent();
|
||||
if (parent instanceof PsiExpressionList) {
|
||||
final PsiElement gParent = parent.getParent();
|
||||
if (gParent instanceof PsiCallExpression) {
|
||||
final PsiMethod resolved = ((PsiCallExpression)gParent).resolveMethod();
|
||||
if (scope.equals(resolved)) {
|
||||
return true;
|
||||
}
|
||||
if (nodeMethod.equals(resolved)) {
|
||||
ref.set(true);
|
||||
return true;
|
||||
}
|
||||
PsiElement parent = PsiTreeUtil.getParentOfType(element, PsiCallExpression.class);
|
||||
while (parent != null) {
|
||||
final PsiMethod resolved = ((PsiCallExpression)parent).resolveMethod();
|
||||
if (scope.equals(resolved)) {
|
||||
return true;
|
||||
}
|
||||
if (nodeMethod.equals(resolved)) {
|
||||
ref.set(true);
|
||||
return true;
|
||||
}
|
||||
parent = PsiTreeUtil.getParentOfType(parent, PsiCallExpression.class, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}) && ref.get()) {
|
||||
return (PsiParameter)resolve;
|
||||
return (PsiParameter)parameter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
</problems>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
interface A<P extends D> {
|
||||
void accept(C<P> c);
|
||||
}
|
||||
|
||||
final class AImpl<P extends D> implements A<P> {
|
||||
private final B<P> m_b = null;
|
||||
|
||||
@Override
|
||||
public final void accept(C<P> c) {
|
||||
m_b.accept(c);
|
||||
}
|
||||
}
|
||||
|
||||
interface B<P extends D> {
|
||||
void accept(C<P> c);
|
||||
}
|
||||
|
||||
interface C<P extends D> {}
|
||||
interface D {}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import java.util.Set;
|
||||
|
||||
class Foo {
|
||||
|
||||
private static void calculate(String p1, String p2, Set<String> p3,
|
||||
String p4, String p5,
|
||||
String p6, Integer p7, Integer p8,
|
||||
Integer p9, Boolean p10, String p11,
|
||||
Integer p12, Integer p13) {
|
||||
validate(p1, p2, p4, p5, p6, p3.toString(), p7, p8, p9, p10, p11, p12, p13);
|
||||
System.out.println(p1);
|
||||
}
|
||||
|
||||
public static void validate(String p1, String p2, String p3, String p4, String p5, String
|
||||
p6, Integer p7, Integer p8, Integer p9, Boolean p10, String p11, Integer p12, Integer p13) {
|
||||
if (p1 == null && p2 == null && p3 == null && p4 == null && p5 == null && p6 == null && p7 == null &&
|
||||
p8 == null && p9 == null && p10 == null && p11 == null && p12 == null && p13 == null)
|
||||
throw new RuntimeException();
|
||||
|
||||
if (p10 != null && (p8 == null && p7 == null && p9 == null))
|
||||
throw new RuntimeException();
|
||||
|
||||
if ((p12 != null || p13 != null) && (p12 == null || p13 == null))
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
import java.util.function.Function;
|
||||
|
||||
class Test {
|
||||
|
||||
{
|
||||
final int[] equals = new int[0];
|
||||
performTest(new Function<String[],String[]>() {
|
||||
public String[] apply(String[] fields) {
|
||||
System.out.println();
|
||||
return getIndexed(fields, equals);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void performTest(Function<String[], String[]> anObject) {
|
||||
String[] fields = new String[0];
|
||||
|
||||
final String[] indexed = anObject.apply(fields);
|
||||
|
||||
System.out.println(indexed);
|
||||
}
|
||||
|
||||
private static String[] getIndexed(String[] fields, int[] indices) {
|
||||
return new String[indices.length];
|
||||
}
|
||||
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
class Test {
|
||||
|
||||
{
|
||||
performTest(new int[0]);
|
||||
}
|
||||
|
||||
private static void performTest(int[] equals) {
|
||||
String[] fields = new String[0];
|
||||
|
||||
<selection>System.out.println();
|
||||
final String[] indexed = getIndexed(fields, equals);</selection>
|
||||
|
||||
System.out.println(indexed);
|
||||
}
|
||||
|
||||
private static String[] getIndexed(String[] fields, int[] indices) {
|
||||
return new String[indices.length];
|
||||
}
|
||||
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class Test {
|
||||
void foo(String s) {
|
||||
bar(s.length());
|
||||
bar(s.length() + 1);
|
||||
}
|
||||
|
||||
void bar(int <caret>i){}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class Test {
|
||||
void foo() {
|
||||
bar();
|
||||
bar();
|
||||
}
|
||||
|
||||
void bar(){}
|
||||
}
|
||||
@@ -102,4 +102,13 @@ public class CanBeFinalTest extends InspectionTestCase {
|
||||
|
||||
doTest(tool);
|
||||
}
|
||||
|
||||
public void testInterfaceMethodInHierarchy() throws Exception {
|
||||
CanBeFinalInspection tool = new CanBeFinalInspection();
|
||||
tool.REPORT_CLASSES = false;
|
||||
tool.REPORT_FIELDS = false;
|
||||
tool.REPORT_METHODS = true;
|
||||
|
||||
doTest(tool);
|
||||
}
|
||||
}
|
||||
|
||||
+18
@@ -468,6 +468,24 @@ public static boolean isBlank(String s) {
|
||||
assert c == ['null -> true']
|
||||
}
|
||||
|
||||
public void "test do not generate too many contract clauses"() {
|
||||
def c = inferContracts("""
|
||||
public static void validate(String p1, String p2, String p3, String p4, String p5, String
|
||||
p6, Integer p7, Integer p8, Integer p9, Boolean p10, String p11, Integer p12, Integer p13) {
|
||||
if (p1 == null && p2 == null && p3 == null && p4 == null && p5 == null && p6 == null && p7 == null && p8 ==
|
||||
null && p9 == null && p10 == null && p11 == null && p12 == null && p13 == null)
|
||||
throw new RuntimeException();
|
||||
|
||||
if (p10 != null && (p8 == null && p7 == null && p9 == null))
|
||||
throw new RuntimeException();
|
||||
|
||||
if ((p12 != null || p13 != null) && (p12 == null || p13 == null))
|
||||
throw new RuntimeException();
|
||||
}
|
||||
""")
|
||||
assert c.size() <= ContractInference.MAX_CONTRACT_COUNT // there could be 74 of them in total
|
||||
}
|
||||
|
||||
public void "test no inference for unused anonymous class methods where annotations won't be used anyway"() {
|
||||
def method = PsiTreeUtil.findChildOfType(myFixture.addClass("""
|
||||
class Foo {{
|
||||
|
||||
@@ -216,6 +216,7 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase {
|
||||
public void testContractAnnotation() { doTest(); }
|
||||
public void testContractInapplicableComparison() { doTest(); }
|
||||
public void testContractInLoopNotTooComplex() { doTest(); }
|
||||
public void testContractWithManyParameters() { doTest(); }
|
||||
public void testContractWithNullable() { doTest(); }
|
||||
public void testContractWithNotNull() { doTest(); }
|
||||
public void testContractPreservesUnknownNullability() { doTest(); }
|
||||
|
||||
@@ -53,6 +53,10 @@ public class IntroduceFunctionalParameterTest extends LightRefactoringTestCase
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testEnsureNotFolded() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
|
||||
@@ -80,6 +80,10 @@ public class SafeDeleteTest extends MultiFileTestCase {
|
||||
doSingleFileTest();
|
||||
}
|
||||
|
||||
public void testDeepDeleteParameterOtherTypeInBinaryExpression() throws Exception {
|
||||
doSingleFileTest();
|
||||
}
|
||||
|
||||
public void testImpossibleToDeepDeleteParameter() throws Exception {
|
||||
doSingleFileTest();
|
||||
}
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
public class RefManagerImpl extends RefManager {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.reference.RefManager");
|
||||
|
||||
private int myLastUsedMask = 256 * 256 * 256 * 4;
|
||||
private int myLastUsedMask = 256 * 256 * 256 * 8;
|
||||
|
||||
@NotNull
|
||||
private final Project myProject;
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.intellij.ide.presentation;
|
||||
|
||||
import com.intellij.ide.TypePresentationService;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.IconUtil;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -26,7 +27,12 @@ import javax.swing.*;
|
||||
* @author yole
|
||||
*/
|
||||
public class VirtualFilePresentation {
|
||||
|
||||
public static Icon getIcon(@NotNull VirtualFile vFile) {
|
||||
return IconUtil.getIcon(vFile, 0, null);
|
||||
}
|
||||
|
||||
public static Icon getIconImpl(@NotNull VirtualFile vFile) {
|
||||
Icon icon = TypePresentationService.getService().getIcon(vFile);
|
||||
if (icon != null) {
|
||||
return icon;
|
||||
|
||||
@@ -132,7 +132,7 @@ public class IconUtil {
|
||||
if (!file.isValid() || project != null && (project.isDisposed() || !wasEverInitialized(project))) return null;
|
||||
|
||||
final Icon providersIcon = getProvidersIcon(file, flags, project);
|
||||
Icon icon = providersIcon == null ? VirtualFilePresentation.getIcon(file) : providersIcon;
|
||||
Icon icon = providersIcon == null ? VirtualFilePresentation.getIconImpl(file) : providersIcon;
|
||||
|
||||
final boolean dumb = project != null && DumbService.getInstance(project).isDumb();
|
||||
for (FileIconPatcher patcher : getPatchers()) {
|
||||
@@ -160,7 +160,7 @@ public class IconUtil {
|
||||
public static Icon getIcon(@NotNull final VirtualFile file, @Iconable.IconFlags final int flags, @Nullable final Project project) {
|
||||
Icon lastIcon = Iconable.LastComputedIcon.get(file, flags);
|
||||
|
||||
final Icon base = lastIcon != null ? lastIcon : VirtualFilePresentation.getIcon(file);
|
||||
final Icon base = lastIcon != null ? lastIcon : VirtualFilePresentation.getIconImpl(file);
|
||||
return IconDeferrer.getInstance().defer(base, new FileIconKey(file, project, flags), ICON_NULLABLE_FUNCTION);
|
||||
}
|
||||
|
||||
|
||||
@@ -128,4 +128,9 @@ public class PathUtil {
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String makeFileName(@NotNull String name, @Nullable String extension) {
|
||||
return name + (StringUtil.isEmpty(extension) ? "" : "." + extension);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
public class PlatformUtils {
|
||||
public static final String PLATFORM_PREFIX_KEY = "idea.platform.prefix";
|
||||
|
||||
// NOTE: If you add any new prefixes to this list, please update the IntelliJPlatformProduct class in DevKit plugin
|
||||
public static final String IDEA_PREFIX = "idea";
|
||||
public static final String IDEA_CE_PREFIX = "Idea";
|
||||
public static final String APPCODE_PREFIX = "AppCode";
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileTypes.InternalFileType;
|
||||
import com.intellij.openapi.progress.ProgressIndicatorProvider;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.FileIndexFacade;
|
||||
@@ -113,9 +114,6 @@ public class PsiManagerImpl extends PsiManagerEx {
|
||||
|
||||
@Override
|
||||
public boolean isInProject(@NotNull PsiElement element) {
|
||||
PsiFile file = element.getContainingFile();
|
||||
if (file != null && file.isPhysical() && file.getViewProvider().getVirtualFile() instanceof LightVirtualFile) return true;
|
||||
|
||||
if (element instanceof PsiDirectoryContainer) {
|
||||
PsiDirectory[] dirs = ((PsiDirectoryContainer)element).getDirectories();
|
||||
for (PsiDirectory dir : dirs) {
|
||||
@@ -124,6 +122,7 @@ public class PsiManagerImpl extends PsiManagerEx {
|
||||
return true;
|
||||
}
|
||||
|
||||
PsiFile file = element.getContainingFile();
|
||||
VirtualFile virtualFile = null;
|
||||
if (file != null) {
|
||||
virtualFile = file.getViewProvider().getVirtualFile();
|
||||
@@ -131,6 +130,8 @@ public class PsiManagerImpl extends PsiManagerEx {
|
||||
else if (element instanceof PsiFileSystemItem) {
|
||||
virtualFile = ((PsiFileSystemItem)element).getVirtualFile();
|
||||
}
|
||||
if (virtualFile instanceof LightVirtualFile) return true;
|
||||
if (virtualFile != null && virtualFile.getFileType() instanceof InternalFileType) return true;
|
||||
|
||||
if (virtualFile != null) {
|
||||
return myExcludedFileIndex.isInContent(virtualFile);
|
||||
|
||||
+15
-4
@@ -33,6 +33,8 @@ import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class DuplicatesInspectionBase extends LocalInspectionTool {
|
||||
private static final int MIN_FRAGMENT_SIZE = 3;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ProblemDescriptor[] checkFile(@NotNull final PsiFile psiFile, @NotNull final InspectionManager manager, final boolean isOnTheFly) {
|
||||
@@ -145,11 +147,10 @@ public class DuplicatesInspectionBase extends LocalInspectionTool {
|
||||
final SmartList<ProblemDescriptor> descriptors = new SmartList<ProblemDescriptor>();
|
||||
|
||||
if (processor != null) {
|
||||
|
||||
for(Map.Entry<Integer, TextRange> entry:processor.reportedRanges.entrySet()) {
|
||||
final Integer offset = entry.getKey();
|
||||
// todo 3 statements constant
|
||||
if (processor.fragmentSize.get(offset) < 3) continue;
|
||||
if (processor.fragmentSize.get(offset) < MIN_FRAGMENT_SIZE) continue;
|
||||
final VirtualFile file = processor.reportedFiles.get(offset);
|
||||
String message = "Found duplicated code in " + file.getPath();
|
||||
|
||||
@@ -158,8 +159,12 @@ public class DuplicatesInspectionBase extends LocalInspectionTool {
|
||||
final int offsetInOtherFile = processor.reportedOffsetInOtherFiles.get(offset);
|
||||
|
||||
LocalQuickFix fix = createNavigateToDupeFix(file, offsetInOtherFile);
|
||||
int hash = processor.fragmentHash.get(offset);
|
||||
|
||||
LocalQuickFix viewAllDupesFix = hash != 0 ? createShowOtherDupesFix(virtualFile, offset, hash, psiFile.getProject()) : null;
|
||||
|
||||
ProblemDescriptor descriptor = manager
|
||||
.createProblemDescriptor(targetElement, rangeInElement, message, ProblemHighlightType.WEAK_WARNING, isOnTheFly, fix);
|
||||
.createProblemDescriptor(targetElement, rangeInElement, message, ProblemHighlightType.WEAK_WARNING, isOnTheFly, fix, viewAllDupesFix);
|
||||
descriptors.add(descriptor);
|
||||
}
|
||||
}
|
||||
@@ -170,6 +175,9 @@ public class DuplicatesInspectionBase extends LocalInspectionTool {
|
||||
protected LocalQuickFix createNavigateToDupeFix(@NotNull VirtualFile file, int offsetInOtherFile) {
|
||||
return null;
|
||||
}
|
||||
protected LocalQuickFix createShowOtherDupesFix(VirtualFile file, int offset, int hash, Project project) {
|
||||
return null;
|
||||
}
|
||||
|
||||
static abstract class DuplicatedCodeProcessor<T> implements FileBasedIndex.ValueProcessor<TIntArrayList> {
|
||||
final TreeMap<Integer, TextRange> reportedRanges = new TreeMap<Integer, TextRange>();
|
||||
@@ -177,10 +185,12 @@ public class DuplicatesInspectionBase extends LocalInspectionTool {
|
||||
final TIntObjectHashMap<PsiElement> reportedPsi = new TIntObjectHashMap<PsiElement>();
|
||||
final TIntIntHashMap reportedOffsetInOtherFiles = new TIntIntHashMap();
|
||||
final TIntIntHashMap fragmentSize = new TIntIntHashMap();
|
||||
final TIntIntHashMap fragmentHash = new TIntIntHashMap();
|
||||
final VirtualFile virtualFile;
|
||||
final Project project;
|
||||
final ProjectFileIndex myProjectFileIndex;
|
||||
T myNode;
|
||||
int myHash;
|
||||
|
||||
DuplicatedCodeProcessor(VirtualFile file, Project project) {
|
||||
virtualFile = file;
|
||||
@@ -191,6 +201,7 @@ public class DuplicatesInspectionBase extends LocalInspectionTool {
|
||||
void process(int hash, T node) {
|
||||
ProgressManager.checkCanceled();
|
||||
myNode = node;
|
||||
myHash = hash;
|
||||
FileBasedIndex.getInstance().processValues(DuplicatesIndex.NAME, hash, null, this, GlobalSearchScope.projectScope(project));
|
||||
}
|
||||
|
||||
@@ -229,7 +240,7 @@ public class DuplicatesInspectionBase extends LocalInspectionTool {
|
||||
reportedOffsetInOtherFiles.put(fragmentStartOffsetInteger, value);
|
||||
reportedPsi.put(fragmentStartOffsetInteger, target);
|
||||
fragmentSize.put(fragmentStartOffsetInteger, newFragmentSize);
|
||||
|
||||
if (newFragmentSize >= MIN_FRAGMENT_SIZE) fragmentHash.put(fragmentStartOffsetInteger, myHash);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -24,6 +24,10 @@ public class CantRunException extends ExecutionException {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public CantRunException(String s, Throwable cause) {
|
||||
super(s, cause);
|
||||
}
|
||||
|
||||
public static CantRunException noModuleConfigured(final String moduleName) {
|
||||
if (moduleName.trim().length() == 0) {
|
||||
return new CantRunException(ExecutionBundle.message("no.module.defined.error.message"));
|
||||
|
||||
+3
-2
@@ -42,9 +42,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsListener;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.ex.RangeHighlighterEx;
|
||||
import com.intellij.openapi.editor.impl.DocumentMarkupModel;
|
||||
import com.intellij.openapi.editor.markup.MarkupModel;
|
||||
@@ -662,6 +660,9 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzerEx implements Pers
|
||||
}
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
hideLastIntentionHint();
|
||||
|
||||
if (editor.getCaretModel().getCaretCount() > 1) return;
|
||||
|
||||
IntentionHintComponent hintComponent = IntentionHintComponent.showIntentionHint(project, file, editor, intentions, false);
|
||||
if (hasToRecreate) {
|
||||
hintComponent.recreate();
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
package com.intellij.execution.util;
|
||||
|
||||
import com.intellij.execution.CantRunException;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class ScriptFileUtil {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(ScriptFileUtil.class);
|
||||
|
||||
private static final String SCHEME = "mem://";
|
||||
private static final Map<String, VirtualFile> ourFilesMap = ContainerUtil.createConcurrentWeakValueMap();
|
||||
private static final AtomicLong ourFileCounter = new AtomicLong();
|
||||
|
||||
private ScriptFileUtil() {}
|
||||
|
||||
public static boolean isMemoryScriptPath(@Nullable String url) {
|
||||
return url != null && url.startsWith(SCHEME);
|
||||
}
|
||||
|
||||
public static String getScriptFilePath(@NotNull VirtualFile file) {
|
||||
if (file.isInLocalFileSystem()) return file.getPath();
|
||||
|
||||
long id = ourFileCounter.incrementAndGet();
|
||||
String url = SCHEME + id + "/" + file.getName();
|
||||
ourFilesMap.put(url, file);
|
||||
return url;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static VirtualFile findScriptFileByPath(@Nullable String path) {
|
||||
if (StringUtil.isEmpty(path)) return null;
|
||||
if (!path.startsWith(SCHEME)) {
|
||||
return LocalFileSystem.getInstance().findFileByPath(path);
|
||||
}
|
||||
return ourFilesMap.get(path);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getLocalFilePath(@NotNull String scriptPath) throws CantRunException {
|
||||
if (isMemoryScriptPath(scriptPath)) {
|
||||
File tmpFile = copyToTempFile(scriptPath);
|
||||
return tmpFile.getAbsolutePath();
|
||||
}
|
||||
if (SystemInfo.isWindows) {
|
||||
return PathUtil.driveLetterToLowerCase(scriptPath);
|
||||
}
|
||||
return scriptPath;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static File copyToTempFile(@NotNull String path) throws CantRunException {
|
||||
VirtualFile virtualFile = findScriptFileByPath(path);
|
||||
if (virtualFile == null) {
|
||||
throw new CantRunException("File not found: " + path);
|
||||
}
|
||||
File ioFile;
|
||||
try {
|
||||
ioFile = FileUtil.createTempFile(virtualFile.getName(), "", true);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new CantRunException("Cannot create temporary file " + virtualFile.getName(), e);
|
||||
}
|
||||
try {
|
||||
copyFile(virtualFile, ioFile);
|
||||
return ioFile;
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new CantRunException("Cannot write temp file " + virtualFile.getPath() + " to " + ioFile.getAbsolutePath(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void copyFile(@NotNull VirtualFile srcFile, @NotNull File destFile) throws IOException {
|
||||
LOG.info("Copying to " + destFile.getPath());
|
||||
CharSequence content = getContent(srcFile);
|
||||
CharBuffer cb = CharBuffer.wrap(content);
|
||||
ByteBuffer bb = CharsetToolkit.UTF8_CHARSET.encode(cb);
|
||||
byte[] result = new byte[bb.remaining()];
|
||||
bb.get(result);
|
||||
FileUtil.writeToFile(destFile, result, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static CharSequence getContent(@NotNull VirtualFile file) {
|
||||
Document document = FileDocumentManager.getInstance().getCachedDocument(file);
|
||||
if (document != null) {
|
||||
return document.getText();
|
||||
}
|
||||
return LoadTextUtil.loadText(file);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -451,10 +451,15 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data
|
||||
nothingToSearchFor();
|
||||
}
|
||||
if (mySearchField instanceof JTextArea) {
|
||||
UIUtil.adjustRows((JTextArea)mySearchField, 2, 6);
|
||||
adjustRows((JTextArea)mySearchField, 2, 6);
|
||||
}
|
||||
}
|
||||
|
||||
private static void adjustRows(JTextArea area, int minRows, int maxRows) {
|
||||
area.setRows(Math.max(minRows, Math.min(maxRows, area.getText().split("\n").length)));
|
||||
}
|
||||
|
||||
|
||||
public boolean isRegexp() {
|
||||
return myFindModel.isRegularExpressions();
|
||||
}
|
||||
@@ -641,7 +646,7 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data
|
||||
setMatchesLimit(LivePreviewController.MATCHES_LIMIT);
|
||||
myFindModel.setStringToReplace(myReplaceField.getText());
|
||||
if (myReplaceField instanceof JTextArea) {
|
||||
UIUtil.adjustRows((JTextArea)myReplaceField, 2, 6);
|
||||
adjustRows((JTextArea)myReplaceField, 2, 6);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1565,7 +1565,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
|
||||
|
||||
private synchronized void buildSymbols(final String pattern) {
|
||||
final SearchResult symbols = getSymbols(pattern, MAX_SYMBOLS, mySymbolsChooseByName);
|
||||
final SearchResult symbols = getSymbols(pattern, MAX_SYMBOLS, showAll.get(), mySymbolsChooseByName);
|
||||
check();
|
||||
|
||||
if (symbols.size() > 0) {
|
||||
@@ -1670,7 +1670,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
}
|
||||
}
|
||||
|
||||
private SearchResult getSymbols(String pattern, final int max, ChooseByNamePopup chooseByNamePopup) {
|
||||
private SearchResult getSymbols(String pattern, final int max, final boolean includeLibs, ChooseByNamePopup chooseByNamePopup) {
|
||||
final SearchResult symbols = new SearchResult();
|
||||
if (!Registry.is("search.everywhere.symbols")) {
|
||||
return symbols;
|
||||
@@ -1678,7 +1678,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
final GlobalSearchScope scope = GlobalSearchScope.projectScope(project);
|
||||
if (chooseByNamePopup == null) return symbols;
|
||||
final ChooseByNameItemProvider provider = chooseByNamePopup.getProvider();
|
||||
provider.filterElements(chooseByNamePopup, pattern, false,
|
||||
provider.filterElements(chooseByNamePopup, pattern, includeLibs,
|
||||
myProgressIndicator, new Processor<Object>() {
|
||||
@Override
|
||||
public boolean process(Object o) {
|
||||
@@ -1687,7 +1687,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
final PsiFile file = element.getContainingFile();
|
||||
if (!myListModel.contains(o) &&
|
||||
//some elements are non-physical like DB columns
|
||||
(file == null || (file.getVirtualFile() != null && scope.accept(file.getVirtualFile())))) {
|
||||
(file == null || (file.getVirtualFile() != null && (includeLibs || scope.accept(file.getVirtualFile()))))) {
|
||||
symbols.add(o);
|
||||
}
|
||||
}
|
||||
@@ -2087,7 +2087,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
= id == WidgetID.CLASSES ? getClasses(pattern, showAll.get(), DEFAULT_MORE_STEP_COUNT, myClassChooseByName)
|
||||
: id == WidgetID.FILES ? getFiles(pattern, DEFAULT_MORE_STEP_COUNT, myFileChooseByName)
|
||||
: id == WidgetID.RUN_CONFIGURATIONS ? getConfigurations(pattern, DEFAULT_MORE_STEP_COUNT)
|
||||
: id == WidgetID.SYMBOLS ? getSymbols(pattern, DEFAULT_MORE_STEP_COUNT, mySymbolsChooseByName)
|
||||
: id == WidgetID.SYMBOLS ? getSymbols(pattern, DEFAULT_MORE_STEP_COUNT, showAll.get(), mySymbolsChooseByName)
|
||||
: id == WidgetID.ACTIONS ? getActionsOrSettings(pattern, DEFAULT_MORE_STEP_COUNT, true)
|
||||
: id == WidgetID.SETTINGS ? getActionsOrSettings(pattern, DEFAULT_MORE_STEP_COUNT, false)
|
||||
: new SearchResult();
|
||||
|
||||
@@ -23,9 +23,7 @@ import com.intellij.lang.StdLanguages;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Caret;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
@@ -39,7 +37,9 @@ import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.LanguageSubstitutors;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -73,7 +73,7 @@ public class NewScratchFileAction extends DumbAwareAction {
|
||||
|
||||
@NotNull
|
||||
public static List<String> getLastUsedLanguagesIds(Project project) {
|
||||
String[] values = PropertiesComponent.getInstance(project).getValues(ScratchpadManager.class.getName());
|
||||
String[] values = PropertiesComponent.getInstance(project).getValues(ScratchFileService.class.getName());
|
||||
return values == null ? ContainerUtil.<String>emptyList() : ContainerUtil.list(values);
|
||||
}
|
||||
|
||||
@@ -111,29 +111,18 @@ public class NewScratchFileAction extends DumbAwareAction {
|
||||
public Language getLanguageFromCaret(@NotNull Project project,
|
||||
@Nullable Editor editor,
|
||||
@Nullable PsiFile psiFile) {
|
||||
if (editor == null) return null;
|
||||
if (psiFile == null) return null;
|
||||
if (editor == null || psiFile == null) return null;
|
||||
Caret caret = editor.getCaretModel().getPrimaryCaret();
|
||||
int offset = caret.getOffset();
|
||||
PsiElement element = InjectedLanguageManager.getInstance(project).findInjectedElementAt(psiFile, offset);
|
||||
element = element == null ? psiFile.findElementAt(offset) : element;
|
||||
Language language = element != null ? element.getLanguage() : psiFile.getLanguage();
|
||||
return substitute(project, language);
|
||||
PsiFile file = element != null ? element.getContainingFile() : psiFile;
|
||||
return file.getLanguage();
|
||||
}
|
||||
|
||||
public static void openNewFile(@NotNull Project project, @NotNull Language language, @NotNull final String text) {
|
||||
FeatureUsageTracker.getInstance().triggerFeatureUsed("scratch");
|
||||
VirtualFile file = ScratchpadManager.getInstance(project).createScratchFile(substitute(project, language));
|
||||
PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
|
||||
final Document document = psiFile == null ? null : PsiDocumentManager.getInstance(project).getDocument(psiFile);
|
||||
if (document != null && StringUtil.isNotEmpty(text)) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
document.setText(text);
|
||||
}
|
||||
});
|
||||
}
|
||||
VirtualFile file = ScratchFileService.getInstance().createScratchFile(project, language, text);
|
||||
if (file == null) return;
|
||||
FileEditorManager.getInstance(project).openFile(file, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ide.scratch;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.PerFileMappings;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class ScratchFileService {
|
||||
|
||||
public static final RootType SCRATCHES = RootType.newRootType("scratches", "Scratches");
|
||||
|
||||
public static ScratchFileService getInstance(@NotNull Project project) {
|
||||
return ServiceManager.getService(project, ScratchFileService.class);
|
||||
}
|
||||
|
||||
public static ScratchFileService getInstance() {
|
||||
return ServiceManager.getService(ScratchFileService.class);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public abstract String getRootPath(@NotNull RootType rootType);
|
||||
|
||||
public abstract boolean isFileInRoot(@NotNull VirtualFile file, @NotNull RootType rootType);
|
||||
|
||||
@Nullable
|
||||
public abstract VirtualFile createScratchFile(@NotNull Project project, @NotNull Language language, @NotNull String initialContent);
|
||||
|
||||
@NotNull
|
||||
public abstract PerFileMappings<Language> getScratchesMapping();
|
||||
|
||||
public static class RootType {
|
||||
private static final Map<String, RootType> ourInstances = ContainerUtil.newLinkedHashMap();
|
||||
|
||||
private final String myId;
|
||||
private final String myDisplayName;
|
||||
|
||||
private RootType(@NotNull String id, @Nullable String displayName) {
|
||||
myId = id;
|
||||
myDisplayName = displayName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getId() {
|
||||
return myId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getDisplayName() {
|
||||
return myDisplayName;
|
||||
}
|
||||
|
||||
public boolean isHidden() {
|
||||
return myDisplayName == null;
|
||||
}
|
||||
|
||||
public static synchronized RootType newRootType(String id, String displayName) {
|
||||
RootType rootType = new RootType(id, displayName);
|
||||
RootType prev = ourInstances.put(id, rootType);
|
||||
if (prev != null) {
|
||||
throw new AssertionError(String.format("rootType '%s' already registered", id));
|
||||
}
|
||||
return rootType;
|
||||
}
|
||||
|
||||
public static synchronized List<RootType> getAllRootTypes() {
|
||||
return ContainerUtil.newArrayList(ourInstances.values());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,338 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ide.scratch;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.FileIconProvider;
|
||||
import com.intellij.ide.navigationToolbar.AbstractNavBarModelExtension;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.LanguageUtil;
|
||||
import com.intellij.lang.PerFileMappings;
|
||||
import com.intellij.lang.PerFileMappingsBase;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.application.RunResult;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.openapi.components.StoragePathMacros;
|
||||
import com.intellij.openapi.fileEditor.impl.NonProjectFileWritingAccessExtension;
|
||||
import com.intellij.openapi.fileTypes.*;
|
||||
import com.intellij.openapi.fileTypes.ex.FileTypeIdentifiableByVirtualFile;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.IdeFrame;
|
||||
import com.intellij.openapi.wm.StatusBar;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.openapi.wm.WindowManagerListener;
|
||||
import com.intellij.psi.LanguageSubstitutor;
|
||||
import com.intellij.psi.LanguageSubstitutors;
|
||||
import com.intellij.ui.LayeredIcon;
|
||||
import com.intellij.ui.UIBundle;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public abstract class ScratchFileServiceImpl extends ScratchFileService {
|
||||
|
||||
public static final LanguageFileType SCRATCH_FILE_TYPE = new MyFileType();
|
||||
|
||||
@State(
|
||||
name = "ScratchFileService",
|
||||
storages = {
|
||||
@Storage(file = StoragePathMacros.APP_CONFIG + "/scratches.xml")
|
||||
})
|
||||
public static class App extends ScratchFileServiceImpl implements PersistentStateComponent<Element> {
|
||||
|
||||
private final MyLanguages myScratchMapping = new MyLanguages();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getRootPath(@NotNull RootType rootType) {
|
||||
return FileUtil.toSystemIndependentName(PathManager.getConfigPath()) + "/" + rootType.getId();
|
||||
}
|
||||
|
||||
public App(WindowManager windowManager) {
|
||||
WindowManagerListener listener = new WindowManagerListener() {
|
||||
@Override
|
||||
public void frameCreated(IdeFrame frame) {
|
||||
Project project = frame.getProject();
|
||||
StatusBar statusBar = frame.getStatusBar();
|
||||
if (project == null || statusBar == null || statusBar.getWidget(ScratchWidget.WIDGET_ID) != null) return;
|
||||
ScratchWidget widget = new ScratchWidget(project);
|
||||
statusBar.addWidget(widget, "before Encoding", project);
|
||||
statusBar.updateWidget(ScratchWidget.WIDGET_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeFrameReleased(IdeFrame frame) {
|
||||
}
|
||||
};
|
||||
for (IdeFrame frame : windowManager.getAllProjectFrames()) {
|
||||
listener.frameCreated(frame);
|
||||
}
|
||||
windowManager.addListener(listener);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PerFileMappings<Language> getScratchesMapping() {
|
||||
return myScratchMapping;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Element getState() {
|
||||
return myScratchMapping.getState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(Element state) {
|
||||
myScratchMapping.loadState(state);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyLanguages extends PerFileMappingsBase<Language> {
|
||||
@Override
|
||||
protected List<Language> getAvailableValues() {
|
||||
return LanguageUtil.getFileLanguages();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected String serialize(Language language) {
|
||||
return language.getID();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected Language handleUnknownMapping(VirtualFile file, String value) {
|
||||
return PlainTextLanguage.INSTANCE;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Language getMapping(@Nullable VirtualFile file) {
|
||||
Language language = super.getMapping(file);
|
||||
if (language == null && file != null && file.getFileType() == SCRATCH_FILE_TYPE) {
|
||||
String extension = file.getExtension();
|
||||
FileType fileType = extension == null ? null : FileTypeManager.getInstance().getFileTypeByExtension(extension);
|
||||
language = fileType instanceof LanguageFileType ? ((LanguageFileType)fileType).getLanguage() : null;
|
||||
}
|
||||
return language;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Prj extends ScratchFileServiceImpl {
|
||||
|
||||
private final Project myProject;
|
||||
|
||||
public Prj(@NotNull Project project) {
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected Project getProject() {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getRootPath(@NotNull RootType rootType) {
|
||||
if (rootType == SCRATCHES) return ScratchFileService.getInstance().getRootPath(rootType);
|
||||
return FileUtil.toSystemIndependentName(StringUtil.notNullize(PathUtil.getParentPath(myProject.getProjectFilePath()))) + "/" + rootType.getId();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public VirtualFile createScratchFile(@NotNull Project project, @NotNull Language language, @NotNull String initialContent) {
|
||||
return ScratchFileService.getInstance().createScratchFile(project, language, initialContent);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PerFileMappings<Language> getScratchesMapping() {
|
||||
return ScratchFileService.getInstance().getScratchesMapping();
|
||||
}
|
||||
}
|
||||
|
||||
public static class TypeFactory extends FileTypeFactory {
|
||||
|
||||
@Override
|
||||
public void createFileTypes(@NotNull FileTypeConsumer consumer) {
|
||||
consumer.consume(SCRATCH_FILE_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Substitutor extends LanguageSubstitutor {
|
||||
@Nullable
|
||||
@Override
|
||||
public Language getLanguage(@NotNull VirtualFile file, @NotNull Project project) {
|
||||
if (file.getFileType() != SCRATCH_FILE_TYPE) return null;
|
||||
PerFileMappings<Language> mapping = ScratchFileService.getInstance().getScratchesMapping();
|
||||
Language language = mapping.getMapping(file);
|
||||
return language != null && language != SCRATCH_FILE_TYPE.getLanguage() ?
|
||||
LanguageSubstitutors.INSTANCE.substituteLanguage(language, file, project) : language;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Highlighter implements SyntaxHighlighterProvider {
|
||||
@Override
|
||||
@Nullable
|
||||
public SyntaxHighlighter create(@NotNull FileType fileType, @Nullable Project project, @Nullable VirtualFile file) {
|
||||
if (fileType == SCRATCH_FILE_TYPE && project != null && file != null) {
|
||||
PerFileMappings<Language> mapping = ScratchFileService.getInstance().getScratchesMapping();
|
||||
Language language = mapping.getMapping(file);
|
||||
return language != null ? SyntaxHighlighterFactory.getSyntaxHighlighter(language, project, file) : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class IconProvider implements FileIconProvider {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Icon getIcon(@NotNull VirtualFile file, @Iconable.IconFlags int flags, @Nullable Project project) {
|
||||
if (project == null || file.getFileType() != SCRATCH_FILE_TYPE) return null;
|
||||
PerFileMappings<Language> mapping = ScratchFileService.getInstance().getScratchesMapping();
|
||||
Language language = ObjectUtils.notNull(mapping.getMapping(file), SCRATCH_FILE_TYPE.getLanguage());
|
||||
LanguageFileType fileType = language.getAssociatedFileType();
|
||||
return fileType == null ? null : LayeredIcon.create(fileType.getIcon(), AllIcons.Actions.Scratch);
|
||||
}
|
||||
}
|
||||
|
||||
public static class AccessExtension implements NonProjectFileWritingAccessExtension {
|
||||
|
||||
@Override
|
||||
public boolean isWritable(@NotNull VirtualFile file) {
|
||||
return file.getFileType() == SCRATCH_FILE_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
public static class NavBarExtension extends AbstractNavBarModelExtension {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getPresentableText(Object object) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<VirtualFile> additionalRoots(Project project) {
|
||||
String path = ScratchFileService.getInstance().getRootPath(SCRATCHES);
|
||||
VirtualFile root = LocalFileSystem.getInstance().findFileByPath(path);
|
||||
return ContainerUtil.createMaybeSingletonList(root);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public VirtualFile createScratchFile(@NotNull Project project, @NotNull final Language language, @NotNull final String initialContent) {
|
||||
RunResult<VirtualFile> result =
|
||||
new WriteCommandAction<VirtualFile>(project, UIBundle.message("file.chooser.create.new.file.command.name")) {
|
||||
@Override
|
||||
protected void run(@NotNull Result<VirtualFile> result) throws Throwable {
|
||||
VirtualFile dir = VfsUtil.createDirectories(getRootPath(SCRATCHES));
|
||||
VirtualFile file = VfsUtil.createChildSequent(LocalFileSystem.getInstance(), dir, "scratch", "");
|
||||
getScratchesMapping().setMapping(file, language);
|
||||
VfsUtil.saveText(file, initialContent);
|
||||
result.setResult(file);
|
||||
}
|
||||
}.execute();
|
||||
if (result.hasException()) {
|
||||
Messages.showMessageDialog(UIBundle.message("create.new.file.could.not.create.file.error.message", "scratch"),
|
||||
UIBundle.message("error.dialog.title"), Messages.getErrorIcon());
|
||||
return null;
|
||||
}
|
||||
return result.getResultObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFileInRoot(@NotNull VirtualFile file, @NotNull RootType rootType) {
|
||||
return rootType == SCRATCHES ? file.getFileType() == SCRATCH_FILE_TYPE : isFileInRootImpl(file, rootType);
|
||||
}
|
||||
|
||||
private static boolean isFileInRootImpl(@NotNull VirtualFile file, RootType scratches) {
|
||||
String rootPath = ScratchFileService.getInstance().getRootPath(scratches);
|
||||
return file.getPath().startsWith(rootPath);
|
||||
}
|
||||
|
||||
private static class MyFileType extends LanguageFileType implements FileTypeIdentifiableByVirtualFile, InternalFileType {
|
||||
|
||||
MyFileType() {
|
||||
super(PlainTextLanguage.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMyFileType(@NotNull VirtualFile file) {
|
||||
return isFileInRootImpl(file, SCRATCHES);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Scratch";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Scratch";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDefaultExtension() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return PlainTextFileType.INSTANCE.getIcon();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getCharset(@NotNull VirtualFile file, @NotNull byte[] content) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ide.scratch;
|
||||
|
||||
import com.intellij.ide.SelectInTarget;
|
||||
import com.intellij.ide.impl.ProjectViewSelectInTarget;
|
||||
import com.intellij.ide.projectView.PresentationData;
|
||||
import com.intellij.ide.projectView.TreeStructureProvider;
|
||||
import com.intellij.ide.projectView.ViewSettings;
|
||||
import com.intellij.ide.projectView.impl.ProjectAbstractTreeStructureBase;
|
||||
import com.intellij.ide.projectView.impl.ProjectTreeStructure;
|
||||
import com.intellij.ide.projectView.impl.ProjectViewPane;
|
||||
import com.intellij.ide.projectView.impl.nodes.BasePsiNode;
|
||||
import com.intellij.ide.util.treeView.AbstractTreeNode;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.NavigatableWithText;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFileSystemItem;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.search.PsiElementProcessor;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author gregsh
|
||||
*/
|
||||
public class ScratchProjectViewPane extends ProjectViewPane {
|
||||
|
||||
public static final String ID = "Scratches";
|
||||
|
||||
public ScratchProjectViewPane(Project project) {
|
||||
super(project);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "Scratches";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return super.getIcon();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProjectAbstractTreeStructureBase createStructure() {
|
||||
return new MyTreeStructure(myProject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWeight() {
|
||||
return 11;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SelectInTarget createSelectInTarget() {
|
||||
return new ProjectViewSelectInTarget(myProject) {
|
||||
@Override
|
||||
public String toString() {
|
||||
return getTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMinorViewId() {
|
||||
return getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getWeight() {
|
||||
return ScratchProjectViewPane.this.getWeight();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected PsiElement getPSIElement(@Nullable Object element) {
|
||||
return element instanceof ScratchFileService.RootType ? getDirectory(myProject, (ScratchFileService.RootType)element) : super.getPSIElement(element);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiDirectory getDirectory(@NotNull Project project, @NotNull ScratchFileService.RootType rootType) {
|
||||
String path = ScratchFileService.getInstance().getRootPath(rootType);
|
||||
VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByPath(path);
|
||||
return virtualFile == null ? null : PsiManager.getInstance(project).findDirectory(virtualFile);
|
||||
}
|
||||
|
||||
private static class MyTreeStructure extends ProjectTreeStructure {
|
||||
|
||||
MyTreeStructure(final Project project) {
|
||||
super(project, ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractTreeNode createRoot(Project project, ViewSettings settings) {
|
||||
return new MyProjectNode(project);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<TreeStructureProvider> getProviders() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class MyProjectNode extends AbstractTreeNode<Project> {
|
||||
MyProjectNode(Project project) {
|
||||
super(project, project);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<? extends AbstractTreeNode> getChildren() {
|
||||
List<AbstractTreeNode> list = ContainerUtil.newArrayList();
|
||||
for (ScratchFileService.RootType rootType : ScratchFileService.RootType.getAllRootTypes()) {
|
||||
if (rootType.isHidden()) continue;
|
||||
list.add(new MyRootNode(getProject(), rootType));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void update(PresentationData presentation) {
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyRootNode extends AbstractTreeNode<ScratchFileService.RootType> {
|
||||
|
||||
MyRootNode(Project project, ScratchFileService.RootType type) {
|
||||
super(project, type);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<? extends AbstractTreeNode> getChildren() {
|
||||
ScratchFileService.RootType rootType = getValue();
|
||||
PsiDirectory directory = getDirectory(getProject(), rootType);
|
||||
if (directory == null) return Collections.emptyList();
|
||||
return new MyPsiNode(getProject(), directory).getChildren();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void update(PresentationData presentation) {
|
||||
presentation.setIcon(PlatformIcons.DIRECTORY_CLOSED_ICON);
|
||||
presentation.setPresentableText(getValue().getDisplayName());
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyPsiNode extends BasePsiNode<PsiFileSystemItem> implements NavigatableWithText {
|
||||
|
||||
MyPsiNode(Project project, PsiFileSystemItem value) {
|
||||
super(project, value, ViewSettings.DEFAULT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlwaysLeaf() {
|
||||
return !getValue().isDirectory();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected Collection<AbstractTreeNode> getChildrenImpl() {
|
||||
if (isAlwaysLeaf()) return Collections.emptyList();
|
||||
final List<AbstractTreeNode> list = ContainerUtil.newArrayList();
|
||||
getValue().processChildren(new PsiElementProcessor<PsiFileSystemItem>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiFileSystemItem element) {
|
||||
list.add(new MyPsiNode(getProject(), element));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateImpl(PresentationData data) {
|
||||
PsiFileSystemItem value = getValue();
|
||||
data.setIcon(value.getIcon(0));
|
||||
data.setPresentableText(value.getName());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getNavigateActionText(boolean focusEditor) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ package com.intellij.ide.scratch;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.PerFileMappings;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
|
||||
@@ -24,11 +25,14 @@ import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.ListPopup;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
|
||||
import com.intellij.openapi.wm.CustomStatusBarWidget;
|
||||
import com.intellij.openapi.wm.StatusBarWidget;
|
||||
import com.intellij.openapi.wm.impl.status.EditorBasedWidget;
|
||||
import com.intellij.openapi.wm.impl.status.TextPanel;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import com.intellij.psi.LanguageSubstitutors;
|
||||
import com.intellij.ui.ClickListener;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.Consumer;
|
||||
@@ -39,6 +43,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.List;
|
||||
|
||||
class ScratchWidget extends EditorBasedWidget implements CustomStatusBarWidget.Multiframe, CustomStatusBarWidget {
|
||||
static final String WIDGET_ID = "Scratch";
|
||||
@@ -50,16 +55,16 @@ class ScratchWidget extends EditorBasedWidget implements CustomStatusBarWidget.M
|
||||
new ClickListener() {
|
||||
@Override
|
||||
public boolean onClick(@NotNull MouseEvent e, int clickCount) {
|
||||
final Project project = getProject();
|
||||
Project project = getProject();
|
||||
Editor editor = getEditor();
|
||||
final LightVirtualFile selectedFile = getScratchFile();
|
||||
if (project == null || editor == null || selectedFile == null) return false;
|
||||
final VirtualFile file = getSelectedFile();
|
||||
if (project == null || editor == null || file == null) return false;
|
||||
final PerFileMappings<Language> fileService = ScratchFileService.getInstance().getScratchesMapping();
|
||||
|
||||
ListPopup popup = NewScratchFileAction.buildLanguagePopup(project, selectedFile.getLanguage(), new Consumer<Language>() {
|
||||
ListPopup popup = NewScratchFileAction.buildLanguagePopup(project, fileService.getMapping(file), new Consumer<Language>() {
|
||||
@Override
|
||||
public void consume(Language language) {
|
||||
selectedFile.setLanguage(NewScratchFileAction.substitute(project, language));
|
||||
FileContentUtilCore.reparseFiles(selectedFile);
|
||||
fileService.setMapping(file, language);
|
||||
update();
|
||||
}
|
||||
});
|
||||
@@ -70,6 +75,17 @@ class ScratchWidget extends EditorBasedWidget implements CustomStatusBarWidget.M
|
||||
return true;
|
||||
}
|
||||
}.installOn(myPanel);
|
||||
myConnection.subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter() {
|
||||
@Override
|
||||
public void after(@NotNull List<? extends VFileEvent> events) {
|
||||
for (VFileEvent event : events) {
|
||||
if (event.getRequestor() == FileContentUtilCore.FORCE_RELOAD_REQUESTOR) {
|
||||
update();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -85,9 +101,16 @@ class ScratchWidget extends EditorBasedWidget implements CustomStatusBarWidget.M
|
||||
}
|
||||
|
||||
private void update() {
|
||||
LightVirtualFile file = getScratchFile();
|
||||
if (file != null) {
|
||||
Language lang = file.getLanguage();
|
||||
Project project = getProject();
|
||||
if (project == null) return;
|
||||
VirtualFile file = getSelectedFile();
|
||||
if (file == null) return;
|
||||
ScratchFileService fileService = ScratchFileService.getInstance();
|
||||
if (fileService.isFileInRoot(file, ScratchFileService.SCRATCHES)) {
|
||||
Language lang = fileService.getScratchesMapping().getMapping(file);
|
||||
if (lang == null) {
|
||||
lang = LanguageSubstitutors.INSTANCE.substituteLanguage(((LanguageFileType)file.getFileType()).getLanguage(), file, project);
|
||||
}
|
||||
myPanel.setText(lang.getDisplayName());
|
||||
myPanel.setBorder(WidgetBorder.INSTANCE);
|
||||
myPanel.setIcon(getDefaultIcon(lang));
|
||||
@@ -102,12 +125,6 @@ class ScratchWidget extends EditorBasedWidget implements CustomStatusBarWidget.M
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private LightVirtualFile getScratchFile() {
|
||||
VirtualFile file = getSelectedFile();
|
||||
return file instanceof LightVirtualFile && file.getFileSystem() instanceof ScratchpadFileSystem ? (LightVirtualFile)file : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StatusBarWidget copy() {
|
||||
return new ScratchWidget(myProject);
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ide.scratch;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.presentation.Presentation;
|
||||
import com.intellij.ide.presentation.PresentationProvider;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.openapi.vfs.VirtualFileSystem;
|
||||
import com.intellij.openapi.vfs.ex.dummy.DummyFileSystem;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import com.intellij.ui.LayeredIcon;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ScratchpadFileSystem extends DummyFileSystem {
|
||||
private static final String PROTOCOL = "scratchpad";
|
||||
private final Map<String, VirtualFile> myCachedFiles = ContainerUtil.newHashMap();
|
||||
|
||||
public static ScratchpadFileSystem getScratchFileSystem() {
|
||||
return (ScratchpadFileSystem)VirtualFileManager.getInstance().getFileSystem(PROTOCOL);
|
||||
}
|
||||
|
||||
public void removeByPrefix(@NotNull final String prefix) {
|
||||
List<String> toRemove = ContainerUtil.findAll(myCachedFiles.keySet(), new Condition<String>() {
|
||||
@Override
|
||||
public boolean value(String s) {
|
||||
return s.startsWith(prefix);
|
||||
}
|
||||
});
|
||||
for (String s : toRemove) {
|
||||
myCachedFiles.remove(s);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualFile findFileByPath(@NotNull String path) {
|
||||
VirtualFile file = myCachedFiles.get(path);
|
||||
if (file != null && file.isValid()) return file;
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public VirtualFile addFile(@NotNull String name, @NotNull Language language, @NotNull String prefix) {
|
||||
VirtualFile file = new MyLightVirtualFile(name, language, prefix);
|
||||
myCachedFiles.put(file.getPath(), file);
|
||||
return file;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getProtocol() {
|
||||
return PROTOCOL;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String extractPresentableUrl(@NotNull String path) {
|
||||
return calcSuffix(findFileByPath(path));
|
||||
}
|
||||
|
||||
private static String calcSuffix(@Nullable VirtualFile file) {
|
||||
return file instanceof LightVirtualFile ? ((LightVirtualFile)file).getLanguage().getDisplayName() : "Unknown language";
|
||||
}
|
||||
|
||||
@Presentation(provider = ScratchPresentation.class)
|
||||
public static class MyLightVirtualFile extends LightVirtualFile {
|
||||
private final String myPrefix;
|
||||
|
||||
public MyLightVirtualFile(@NotNull String fileName, @NotNull Language language, @NotNull String projectPrefix) {
|
||||
super(fileName, language, "");
|
||||
myPrefix = projectPrefix;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public VirtualFileSystem getFileSystem() {
|
||||
return getScratchFileSystem();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getPath() {
|
||||
return myPrefix + super.getPath();
|
||||
}
|
||||
}
|
||||
|
||||
public static class ScratchPresentation extends PresentationProvider<LightVirtualFile> {
|
||||
@Override
|
||||
public Icon getIcon(@NotNull LightVirtualFile file) {
|
||||
return LayeredIcon.create(file.getFileType().getIcon(), AllIcons.Actions.New);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ide.scratch;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.FileIconProvider;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.LayeredIcon;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class ScratchpadIconProvider implements FileIconProvider {
|
||||
@Nullable
|
||||
@Override
|
||||
public Icon getIcon(@NotNull VirtualFile file, @Iconable.IconFlags int flags, @Nullable Project project) {
|
||||
if (file instanceof ScratchpadFileSystem.MyLightVirtualFile) {
|
||||
return LayeredIcon.create(file.getFileType().getIcon(), AllIcons.Actions.Scratch);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ide.scratch;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class ScratchpadManager {
|
||||
public static ScratchpadManager getInstance(@NotNull Project project) {
|
||||
return ServiceManager.getService(project, ScratchpadManager.class);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public abstract VirtualFile createScratchFile(@NotNull Language language);
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ide.scratch;
|
||||
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.StatusBar;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ScratchpadManagerImpl extends ScratchpadManager implements Disposable {
|
||||
private final Project myProject;
|
||||
private Integer myIndex = 0;
|
||||
|
||||
public ScratchpadManagerImpl(@NotNull Project project) {
|
||||
myProject = project;
|
||||
StatusBar statusBar = WindowManager.getInstance().getStatusBar(myProject);
|
||||
if (statusBar == null) return;
|
||||
if (statusBar.getWidget(ScratchWidget.WIDGET_ID) != null) return;
|
||||
ScratchWidget widget = new ScratchWidget(myProject);
|
||||
statusBar.addWidget(widget, "before Encoding", myProject);
|
||||
statusBar.updateWidget(ScratchWidget.WIDGET_ID);
|
||||
project.getMessageBus().connect(project).subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, widget);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public VirtualFile createScratchFile(@NotNull final Language language) {
|
||||
updateHistory(myProject, language);
|
||||
|
||||
return ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() {
|
||||
@Override
|
||||
public VirtualFile compute() {
|
||||
String name = generateFileName();
|
||||
return ScratchpadFileSystem.getScratchFileSystem().addFile(name, language, calculatePrefix(ScratchpadManagerImpl.this.myProject));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void updateHistory(Project project, Language language) {
|
||||
String[] values = PropertiesComponent.getInstance(project).getValues(ScratchpadManager.class.getName());
|
||||
List<String> lastUsed = ContainerUtil.newArrayListWithCapacity(5);
|
||||
lastUsed.add(language.getID());
|
||||
if (values != null) {
|
||||
for (String value : values) {
|
||||
if (!lastUsed.contains(value)) {
|
||||
lastUsed.add(value);
|
||||
}
|
||||
if (lastUsed.size() == 5) break;
|
||||
}
|
||||
}
|
||||
PropertiesComponent.getInstance(project).setValues(ScratchpadManager.class.getName(), ArrayUtil.toStringArray(lastUsed));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String calculatePrefix(@NotNull Project project) {
|
||||
return project.getLocationHash();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String generateFileName() {
|
||||
int updated = myIndex++;
|
||||
String index = updated == 0 ? "" : "." + updated;
|
||||
return "scratch" + index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
ScratchpadFileSystem.getScratchFileSystem().removeByPrefix(calculatePrefix(myProject));
|
||||
}
|
||||
}
|
||||
+5
-1
@@ -21,6 +21,7 @@ import com.intellij.openapi.command.UndoConfirmationPolicy;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -148,7 +149,10 @@ public abstract class EditorAction extends AnAction implements DumbAware {
|
||||
@Override
|
||||
public Object getData(String dataId) {
|
||||
if (PROJECT.is(dataId)) {
|
||||
return editor.getProject();
|
||||
final Project project = editor.getProject();
|
||||
if (project != null) {
|
||||
return project;
|
||||
}
|
||||
}
|
||||
return original.getData(dataId);
|
||||
}
|
||||
|
||||
@@ -1673,7 +1673,11 @@ public class Messages {
|
||||
return myExitFunc.fun(exitCode, myCheckBox);
|
||||
}
|
||||
|
||||
return exitCode == OK_EXIT_CODE ? myCheckBox.isSelected() ? OK_EXIT_CODE : CANCEL_EXIT_CODE : CANCEL_EXIT_CODE;
|
||||
boolean checkBoxSelected = (myCheckBox != null && myCheckBox.isSelected());
|
||||
|
||||
boolean okExitCode = (exitCode == OK_EXIT_CODE);
|
||||
|
||||
return checkBoxSelected && okExitCode ? OK_EXIT_CODE : CANCEL_EXIT_CODE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,10 +26,7 @@ import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.SystemProperties;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import com.intellij.util.lang.UrlClassLoader;
|
||||
@@ -435,10 +432,11 @@ public class VfsUtil extends VfsUtilCore {
|
||||
}
|
||||
|
||||
public static VirtualFile createChildSequent(Object requestor, @NotNull VirtualFile dir, @NotNull String prefix, @NotNull String extension) throws IOException {
|
||||
String fileName = prefix + "." + extension;
|
||||
String dotExt = PathUtil.makeFileName("", extension);
|
||||
String fileName = prefix + dotExt;
|
||||
int i = 1;
|
||||
while (dir.findChild(fileName) != null) {
|
||||
fileName = prefix + i + "." + extension;
|
||||
fileName = prefix + i + dotExt;
|
||||
i++;
|
||||
}
|
||||
return dir.createChildData(requestor, fileName);
|
||||
|
||||
@@ -66,6 +66,8 @@ public class JBViewport extends JViewport implements ZoomableViewport {
|
||||
};
|
||||
|
||||
private StatusText myEmptyText;
|
||||
private boolean myPaintingNow;
|
||||
|
||||
private ZoomingDelegate myZoomer;
|
||||
|
||||
private Dimension myTempViewSize;
|
||||
@@ -112,6 +114,7 @@ public class JBViewport extends JViewport implements ZoomableViewport {
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
myPaintingNow = true;
|
||||
if (myZoomer != null && myZoomer.isActive()) {
|
||||
myZoomer.paint(g);
|
||||
}
|
||||
@@ -122,6 +125,7 @@ public class JBViewport extends JViewport implements ZoomableViewport {
|
||||
myEmptyText.paint(this, g);
|
||||
}
|
||||
}
|
||||
myPaintingNow = false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -147,4 +151,8 @@ public class JBViewport extends JViewport implements ZoomableViewport {
|
||||
public void magnify(double magnification) {
|
||||
myZoomer.magnify(magnification);
|
||||
}
|
||||
|
||||
public boolean isPaintingNow() {
|
||||
return myPaintingNow;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import com.intellij.ui.ClickListener;
|
||||
import com.intellij.ui.SimpleColoredComponent;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.ui.UIBundle;
|
||||
import com.intellij.ui.components.JBViewport;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -186,13 +188,37 @@ public abstract class StatusText {
|
||||
}
|
||||
|
||||
public void paint(Component owner, Graphics g) {
|
||||
boolean wrongComponent = owner != myOwner && owner != null && owner.getParent() != myOwner;
|
||||
if (!isStatusVisible() || wrongComponent) return;
|
||||
if (!isStatusVisible()) return;
|
||||
|
||||
Rectangle b = getTextComponentBound();
|
||||
myComponent.setBounds(0, 0, b.width, b.height);
|
||||
if (owner == myOwner) {
|
||||
doPaintStatusText(g, getTextComponentBound());
|
||||
}
|
||||
else {
|
||||
paintOnComponentUnderViewport(owner, g);
|
||||
}
|
||||
}
|
||||
|
||||
Graphics2D g2 = (Graphics2D)g.create(b.x, b.y, b.width, b.height);
|
||||
private void paintOnComponentUnderViewport(Component component, Graphics g) {
|
||||
JBViewport viewport = ObjectUtils.tryCast(myOwner, JBViewport.class);
|
||||
if (viewport == null || viewport.getView() != component || viewport.isPaintingNow()) return;
|
||||
|
||||
// We're painting a component which has a viewport as it's ancestor.
|
||||
// As the viewport paints status text, we'll erase it, so we need to schedule a repaint for the viewport with status text's bounds.
|
||||
// But it causes flicker, so we paint status text over the component first and then schedule the viewport repaint.
|
||||
|
||||
Rectangle textBoundsInViewport = getTextComponentBound();
|
||||
|
||||
int xInOwner = textBoundsInViewport.x - component.getX();
|
||||
int yInOwner = textBoundsInViewport.y - component.getY();
|
||||
Rectangle textBoundsInOwner = new Rectangle(xInOwner, yInOwner, textBoundsInViewport.width, textBoundsInViewport.height);
|
||||
doPaintStatusText(g, textBoundsInOwner);
|
||||
|
||||
viewport.repaint(textBoundsInViewport);
|
||||
}
|
||||
|
||||
private void doPaintStatusText(Graphics g, Rectangle textComponentBounds) {
|
||||
myComponent.setBounds(0, 0, textComponentBounds.width, textComponentBounds.height);
|
||||
Graphics2D g2 = (Graphics2D)g.create(textComponentBounds.x, textComponentBounds.y, textComponentBounds.width, textComponentBounds.height);
|
||||
myComponent.paint(g2);
|
||||
g2.dispose();
|
||||
}
|
||||
|
||||
@@ -1161,7 +1161,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
@Override
|
||||
@NotNull
|
||||
public VisualPosition xyToVisualPosition(@NotNull Point p) {
|
||||
int line = yPositionToVisibleLine(p.y);
|
||||
int line = yPositionToVisibleLine(Math.max(p.y, 0));
|
||||
int px = p.x;
|
||||
if (line == 0 && myPrefixText != null) {
|
||||
px -= myPrefixWidthInPixels;
|
||||
|
||||
+1
-2
@@ -55,7 +55,6 @@ import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.io.FileUtilRt;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.openapi.vfs.ex.dummy.DummyFileSystem;
|
||||
import com.intellij.openapi.vfs.newvfs.NewVirtualFileSystem;
|
||||
import com.intellij.pom.core.impl.PomModelImpl;
|
||||
import com.intellij.psi.ExternalChangeAction;
|
||||
@@ -190,7 +189,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Virt
|
||||
document.putUserData(FILE_KEY, file);
|
||||
}
|
||||
|
||||
if (!(file instanceof LightVirtualFile || file.getFileSystem() instanceof DummyFileSystem)) {
|
||||
if (!(file instanceof LightVirtualFile || file.getFileSystem() instanceof NonPhysicalFileSystem)) {
|
||||
document.addDocumentListener(
|
||||
new DocumentAdapter() {
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -274,7 +274,7 @@ public class IdeSettingsDialog extends DialogWrapper implements DataProvider {
|
||||
if (OptionsEditor.KEY.is(dataId)) {
|
||||
return myEditor;
|
||||
}
|
||||
return null;
|
||||
return myEditor == null ? null : myEditor.getData(dataId);
|
||||
}
|
||||
|
||||
private class ApplyAction extends AbstractAction {
|
||||
|
||||
+13
-2
@@ -131,8 +131,19 @@ public class GlassPaneDialogWrapperPeer extends DialogWrapperPeer implements Foc
|
||||
private void createDialog(final Window owner) throws GlasspanePeerUnavailableException {
|
||||
Window active = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
|
||||
if (!(active instanceof JDialog) && owner instanceof IdeFrame) {
|
||||
final JFrame frame = (JFrame) owner;
|
||||
final JComponent glassPane = (JComponent) frame.getGlassPane();
|
||||
|
||||
Component glassPane;
|
||||
|
||||
// Not all successor of IdeFrame are frames
|
||||
if (owner instanceof JFrame) {
|
||||
glassPane = ((JFrame)owner).getGlassPane();
|
||||
}
|
||||
else if (owner instanceof JDialog) {
|
||||
glassPane = ((JDialog)owner).getGlassPane();
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Cannot find glass pane for " + owner.getClass().getName());
|
||||
}
|
||||
|
||||
assert glassPane instanceof IdeGlassPaneEx : "GlassPane should be instance of IdeGlassPane!";
|
||||
myDialog = new MyDialog((IdeGlassPaneEx) glassPane, myWrapper, myProject);
|
||||
|
||||
@@ -210,9 +210,15 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
|
||||
|
||||
myActivityMonitor.addActivity(FOCUS, ModalityState.any());
|
||||
if (!forced) {
|
||||
if (!myFocusRequests.contains(command)) {
|
||||
myFocusRequests.add(command);
|
||||
}
|
||||
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!myFocusRequests.contains(command)) {
|
||||
myFocusRequests.add(command);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
@@ -385,15 +391,23 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void setCommand(@NotNull FocusCommand command) {
|
||||
private void setCommand(@NotNull final FocusCommand command) {
|
||||
myRequestFocusCmd = command;
|
||||
|
||||
if (!myFocusRequests.contains(command)) {
|
||||
myFocusRequests.add(command);
|
||||
}
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!myFocusRequests.contains(command)) {
|
||||
myFocusRequests.add(command);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void resetCommand(@NotNull FocusCommand cmd, boolean reject) {
|
||||
private void resetCommand(@NotNull final FocusCommand cmd, boolean reject) {
|
||||
|
||||
assertDispatchThread();
|
||||
|
||||
if (cmd == myRequestFocusCmd) {
|
||||
myRequestFocusCmd = null;
|
||||
}
|
||||
@@ -403,7 +417,12 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
|
||||
processor.finish(myKeyProcessorContext);
|
||||
}
|
||||
|
||||
myFocusRequests.remove(cmd);
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myFocusRequests.remove(cmd);
|
||||
}
|
||||
});
|
||||
|
||||
if (reject) {
|
||||
ActionCallback cb = cmd.getCallback();
|
||||
@@ -413,8 +432,13 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private void resetUnforcedCommand(@NotNull FocusCommand cmd) {
|
||||
myFocusRequests.remove(cmd);
|
||||
private void resetUnforcedCommand(@NotNull final FocusCommand cmd) {
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myFocusRequests.remove(cmd);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean canExecuteOnInactiveApplication(@NotNull FocusCommand cmd) {
|
||||
@@ -666,20 +690,26 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
|
||||
}
|
||||
|
||||
private void invalidateFocusRequestsQueue() {
|
||||
if (myFocusRequests.isEmpty()) return;
|
||||
assertDispatchThread();
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myFocusRequests.isEmpty()) return;
|
||||
|
||||
FocusCommand[] requests = myFocusRequests.toArray(new FocusCommand[myFocusRequests.size()]);
|
||||
boolean wasChanged = false;
|
||||
for (FocusCommand each : requests) {
|
||||
if (each.isExpired()) {
|
||||
resetCommand(each, true);
|
||||
wasChanged = true;
|
||||
FocusCommand[] requests = myFocusRequests.toArray(new FocusCommand[myFocusRequests.size()]);
|
||||
boolean wasChanged = false;
|
||||
for (FocusCommand each : requests) {
|
||||
if (each.isExpired()) {
|
||||
resetCommand(each, true);
|
||||
wasChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (wasChanged && myFocusRequests.isEmpty()) {
|
||||
restartIdleAlarm();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wasChanged && myFocusRequests.isEmpty()) {
|
||||
restartIdleAlarm();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isIdleQueueEmpty() {
|
||||
@@ -695,6 +725,8 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
|
||||
if (!isTypeaheadEnabled()) return false;
|
||||
if (isFlushingIdleRequests()) return false;
|
||||
|
||||
assertDispatchThread();
|
||||
|
||||
if (!isFocusTransferReady() || !isPendingKeyEventsRedispatched() || !myTypeAheadRequestors.isEmpty()) {
|
||||
for (FocusCommand each : myFocusRequests) {
|
||||
final KeyEventProcessor processor = each.getProcessor();
|
||||
|
||||
@@ -49,7 +49,7 @@ public class JBMacMessages extends MacMessagesEmulation {
|
||||
window = getForemostWindow(null);
|
||||
}
|
||||
SheetMessage sheetMessage = new SheetMessage(window, title, message, UIUtil.getQuestionIcon(),
|
||||
new String [] {defaultButton, alternateButton, otherButton}, null, defaultButton, alternateButton);
|
||||
new String [] {defaultButton, alternateButton, otherButton}, doNotAskOption, defaultButton, alternateButton);
|
||||
String resultString = sheetMessage.getResult();
|
||||
int result = resultString.equals(defaultButton) ? Messages.YES : resultString.equals(alternateButton) ? Messages.NO : Messages.CANCEL;
|
||||
if (doNotAskOption != null) {
|
||||
|
||||
@@ -31,6 +31,9 @@ public class RecentTasks {
|
||||
private final static WeakReference<Thread> openerThread =
|
||||
new WeakReference<Thread>(Thread.currentThread());
|
||||
|
||||
private final static String openerThreadName =
|
||||
Thread.currentThread().getName();
|
||||
|
||||
static {
|
||||
UrlClassLoader.loadPlatformLibrary("jumpListBridge");
|
||||
}
|
||||
@@ -71,6 +74,6 @@ public class RecentTasks {
|
||||
private static void checkThread() {
|
||||
Thread t = openerThread.get();
|
||||
if (t == null || !t.equals(Thread.currentThread()))
|
||||
throw new RuntimeException("This class has to be used from the same thread");
|
||||
throw new RuntimeException("Current thread is " + Thread.currentThread().getName() + "This class has to be used from " + openerThreadName + " thread");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -612,6 +612,8 @@ action.IntroduceConstant.text=_Constant...
|
||||
action.IntroduceConstant.description=Replace selected expression with a constant (static final field)
|
||||
action.IntroduceParameter.text=_Parameter...
|
||||
action.IntroduceParameter.description=Turn the selected expression into method parameter
|
||||
action.IntroduceFunctionalParameter.text=Functiona_l Parameter...
|
||||
action.IntroduceFunctionalParameter.description=Replace selected statements with a call to new functional method parameter
|
||||
action.ExtractInterface.text=_Interface...
|
||||
action.ExtractInterface.description=Extract interface from the selected class
|
||||
action.ExtractModule.text=_Module...
|
||||
|
||||
@@ -787,3 +787,4 @@ rename.project.handler.title=Rename &project
|
||||
enter.new.project.name=Enter new project name:
|
||||
rename.project=Rename Project
|
||||
renames.project=Renames project
|
||||
introduce.functional.parameter.title=Extract Functional Parameter
|
||||
|
||||
@@ -328,8 +328,17 @@
|
||||
<projectService serviceInterface="com.intellij.openapi.roots.impl.LibraryScopeCache"
|
||||
serviceImplementation="com.intellij.openapi.roots.impl.LibraryScopeCache"/>
|
||||
|
||||
<projectService serviceInterface="com.intellij.ide.scratch.ScratchpadManager"
|
||||
serviceImplementation="com.intellij.ide.scratch.ScratchpadManagerImpl"/>
|
||||
<applicationService serviceInterface="com.intellij.ide.scratch.ScratchFileService"
|
||||
serviceImplementation="com.intellij.ide.scratch.ScratchFileServiceImpl$App"/>
|
||||
<projectService serviceInterface="com.intellij.ide.scratch.ScratchFileService"
|
||||
serviceImplementation="com.intellij.ide.scratch.ScratchFileServiceImpl$Prj"/>
|
||||
<fileTypeFactory implementation="com.intellij.ide.scratch.ScratchFileServiceImpl$TypeFactory"/>
|
||||
<fileIconProvider implementation="com.intellij.ide.scratch.ScratchFileServiceImpl$IconProvider"/>
|
||||
<lang.substitutor language="TEXT" implementationClass="com.intellij.ide.scratch.ScratchFileServiceImpl$Substitutor" order="first"/>
|
||||
<syntaxHighlighter factoryClass="com.intellij.ide.scratch.ScratchFileServiceImpl$Highlighter" order="first"/>
|
||||
<nonProjectFileWritingAccessExtension implementation="com.intellij.ide.scratch.ScratchFileServiceImpl$AccessExtension"/>
|
||||
<navbar implementation="com.intellij.ide.scratch.ScratchFileServiceImpl$NavBarExtension"/>
|
||||
<projectViewPane implementation="com.intellij.ide.scratch.ScratchProjectViewPane"/>
|
||||
|
||||
<colorSettingsPage implementation="com.intellij.openapi.options.colors.pages.GeneralColorsPage" id="general"/>
|
||||
<colorSettingsPage implementation="com.intellij.openapi.options.colors.pages.DefaultLanguageColorsPage" id="defaultLanguage"/>
|
||||
@@ -868,9 +877,6 @@
|
||||
|
||||
<lang.foldingBuilder language="TEXT" implementationClass="com.intellij.ide.highlighter.custom.impl.CustomFileTypeFoldingBuilder"/>
|
||||
|
||||
<virtualFileSystem key="scratchpad" implementationClass="com.intellij.ide.scratch.ScratchpadFileSystem"/>
|
||||
<fileIconProvider implementation="com.intellij.ide.scratch.ScratchpadIconProvider"/>
|
||||
|
||||
<applicationService serviceImplementation="com.intellij.openapi.editor.richcopy.settings.RichCopySettings"/>
|
||||
<copyPastePostProcessor implementation="com.intellij.openapi.editor.richcopy.TextWithMarkupProcessor"/>
|
||||
<!--the following binding uses 'first' order to make sure it captures raw text before any other processor modifies it -->
|
||||
|
||||
@@ -716,6 +716,9 @@
|
||||
<action id="IntroduceParameter">
|
||||
<keyboard-shortcut first-keystroke="control alt P"/>
|
||||
</action>
|
||||
<action id="IntroduceFunctionalParameter">
|
||||
<keyboard-shortcut first-keystroke="control alt shift P"/>
|
||||
</action>
|
||||
<action id="NextOccurence">
|
||||
<keyboard-shortcut first-keystroke="control alt DOWN"/>
|
||||
</action>
|
||||
|
||||
@@ -15,214 +15,23 @@
|
||||
*/
|
||||
package com.intellij.lang;
|
||||
|
||||
import com.intellij.injected.editor.VirtualFileWindow;
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.impl.FilePropertyPusher;
|
||||
import com.intellij.openapi.roots.impl.PushedFilePropertiesUpdater;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public abstract class LanguagePerFileMappings<T> implements PersistentStateComponent<Element>, PerFileMappings<T> {
|
||||
public abstract class LanguagePerFileMappings<T> extends PerFileMappingsBase<T> implements PerFileMappings<T> {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("com.intellij.lang.LanguagePerFileMappings");
|
||||
|
||||
private final Map<VirtualFile, T> myMappings = new HashMap<VirtualFile, T>();
|
||||
private final Project myProject;
|
||||
|
||||
public LanguagePerFileMappings(final Project project) {
|
||||
public LanguagePerFileMappings(@NotNull Project project) {
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected FilePropertyPusher<T> getFilePropertyPusher() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<VirtualFile, T> getMappings() {
|
||||
synchronized (myMappings) {
|
||||
cleanup();
|
||||
return Collections.unmodifiableMap(myMappings);
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanup() {
|
||||
for (final VirtualFile file : new ArrayList<VirtualFile>(myMappings.keySet())) {
|
||||
if (file != null //PROJECT, top-level
|
||||
&& !file.isValid()) {
|
||||
myMappings.remove(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public T getMapping(@Nullable VirtualFile file) {
|
||||
FilePropertyPusher<T> pusher = getFilePropertyPusher();
|
||||
T t = getMappingInner(file, myMappings, pusher == null? null : pusher.getFileDataKey());
|
||||
return t == null? getDefaultMapping(file) : t;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected static <T> T getMappingInner(@Nullable VirtualFile file, @Nullable Map<VirtualFile, T> mappings, @Nullable Key<T> pusherKey) {
|
||||
if (file instanceof VirtualFileWindow) {
|
||||
final VirtualFileWindow window = (VirtualFileWindow)file;
|
||||
file = window.getDelegate();
|
||||
}
|
||||
VirtualFile originalFile = file instanceof LightVirtualFile ? ((LightVirtualFile)file).getOriginalFile() : null;
|
||||
if (Comparing.equal(originalFile, file)) originalFile = null;
|
||||
|
||||
if (file != null) {
|
||||
final T pushedValue = pusherKey == null? null : file.getUserData(pusherKey);
|
||||
if (pushedValue != null) return pushedValue;
|
||||
}
|
||||
if (originalFile != null) {
|
||||
final T pushedValue = pusherKey == null? null : originalFile.getUserData(pusherKey);
|
||||
if (pushedValue != null) return pushedValue;
|
||||
}
|
||||
if (mappings == null) return null;
|
||||
synchronized (mappings) {
|
||||
for (VirtualFile cur = file; ; cur = cur.getParent()) {
|
||||
T t = mappings.get(cur);
|
||||
if (t != null) return t;
|
||||
if (originalFile != null) {
|
||||
t = mappings.get(originalFile);
|
||||
if (t != null) return t;
|
||||
originalFile = originalFile.getParent();
|
||||
}
|
||||
if (cur == null) break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T chosenToStored(VirtualFile file, T value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelectable(T value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public T getDefaultMapping(@Nullable final VirtualFile file) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T getImmediateMapping(@Nullable final VirtualFile file) {
|
||||
synchronized (myMappings) {
|
||||
return myMappings.get(file);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMappings(final Map<VirtualFile, T> mappings) {
|
||||
final Collection<VirtualFile> oldFiles;
|
||||
synchronized (myMappings) {
|
||||
oldFiles = new ArrayList<VirtualFile>(myMappings.keySet());
|
||||
myMappings.clear();
|
||||
myMappings.putAll(mappings);
|
||||
cleanup();
|
||||
}
|
||||
handleMappingChange(mappings.keySet(), oldFiles, !getProject().isDefault());
|
||||
}
|
||||
|
||||
public void setMapping(@Nullable final VirtualFile file, @Nullable T dialect) {
|
||||
synchronized (myMappings) {
|
||||
if (dialect == null) {
|
||||
myMappings.remove(file);
|
||||
}
|
||||
else {
|
||||
myMappings.put(file, dialect);
|
||||
}
|
||||
}
|
||||
final List<VirtualFile> files = ContainerUtil.createMaybeSingletonList(file);
|
||||
handleMappingChange(files, files, false);
|
||||
}
|
||||
|
||||
private void handleMappingChange(final Collection<VirtualFile> files, Collection<VirtualFile> oldFiles, final boolean includeOpenFiles) {
|
||||
final FilePropertyPusher<T> pusher = getFilePropertyPusher();
|
||||
if (pusher != null) {
|
||||
for (VirtualFile oldFile : oldFiles) {
|
||||
if (oldFile == null) continue; // project
|
||||
oldFile.putUserData(pusher.getFileDataKey(), null);
|
||||
}
|
||||
PushedFilePropertiesUpdater updater = PushedFilePropertiesUpdater.getInstance(myProject);
|
||||
if (updater == null) {
|
||||
if (!myProject.isDefault()) {
|
||||
LOG.error("updater = null. project=" + myProject.getName()+", this="+getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
else {
|
||||
updater.pushAll(pusher);
|
||||
}
|
||||
}
|
||||
if (shouldReparseFiles()) {
|
||||
PsiDocumentManager.getInstance(myProject).reparseFiles(files, includeOpenFiles);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<T> getAvailableValues(VirtualFile file) {
|
||||
return getAvailableValues();
|
||||
}
|
||||
|
||||
protected abstract List<T> getAvailableValues();
|
||||
|
||||
@Nullable
|
||||
protected abstract String serialize(T t);
|
||||
|
||||
@Override
|
||||
public Element getState() {
|
||||
synchronized (myMappings) {
|
||||
cleanup();
|
||||
final Element element = new Element("x");
|
||||
final List<VirtualFile> files = new ArrayList<VirtualFile>(myMappings.keySet());
|
||||
Collections.sort(files, new Comparator<VirtualFile>() {
|
||||
@Override
|
||||
public int compare(final VirtualFile o1, final VirtualFile o2) {
|
||||
if (o1 == null || o2 == null) return o1 == null ? o2 == null ? 0 : 1 : -1;
|
||||
return o1.getPath().compareTo(o2.getPath());
|
||||
}
|
||||
});
|
||||
for (VirtualFile file : files) {
|
||||
final T dialect = myMappings.get(file);
|
||||
String value = serialize(dialect);
|
||||
if (value != null) {
|
||||
final Element child = new Element("file");
|
||||
element.addContent(child);
|
||||
child.setAttribute("url", file == null ? "PROJECT" : file.getUrl());
|
||||
child.setAttribute(getValueAttribute(), value);
|
||||
}
|
||||
}
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected T handleUnknownMapping(VirtualFile file, String value) {
|
||||
return null;
|
||||
@NotNull
|
||||
protected Project getProject() {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -230,52 +39,4 @@ public abstract class LanguagePerFileMappings<T> implements PersistentStateCompo
|
||||
return "dialect";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(final Element state) {
|
||||
synchronized (myMappings) {
|
||||
final THashMap<String, T> dialectMap = new THashMap<String, T>();
|
||||
for (T dialect : getAvailableValues()) {
|
||||
String key = serialize(dialect);
|
||||
if (key != null) {
|
||||
dialectMap.put(key, dialect);
|
||||
}
|
||||
}
|
||||
final List<Element> files = state.getChildren("file");
|
||||
for (Element fileElement : files) {
|
||||
final String url = fileElement.getAttributeValue("url");
|
||||
final String dialectID = fileElement.getAttributeValue(getValueAttribute());
|
||||
final VirtualFile file = url.equals("PROJECT") ? null : VirtualFileManager.getInstance().findFileByUrl(url);
|
||||
T dialect = dialectMap.get(dialectID);
|
||||
if (dialect == null) {
|
||||
dialect = handleUnknownMapping(file, dialectID);
|
||||
if (dialect == null) continue;
|
||||
}
|
||||
if (file != null || url.equals("PROJECT")) {
|
||||
myMappings.put(file, dialect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public void cleanupForNextTest() {
|
||||
synchronized (myMappings) {
|
||||
myMappings.clear();
|
||||
}
|
||||
}
|
||||
|
||||
protected Project getProject() {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
protected boolean shouldReparseFiles() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean hasMappings() {
|
||||
synchronized (myMappings) {
|
||||
return !myMappings.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.intellij.lang;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -26,20 +27,23 @@ import java.util.Map;
|
||||
* @author Dmitry Avdeev
|
||||
*/
|
||||
public interface PerFileMappings<T> {
|
||||
|
||||
|
||||
@NotNull
|
||||
Map<VirtualFile, T> getMappings();
|
||||
|
||||
void setMappings(Map<VirtualFile, T> mappings);
|
||||
void setMappings(@NotNull Map<VirtualFile, T> mappings);
|
||||
|
||||
Collection<T> getAvailableValues(final VirtualFile file);
|
||||
void setMapping(@Nullable VirtualFile file, T value);
|
||||
|
||||
Collection<T> getAvailableValues(VirtualFile file);
|
||||
|
||||
@Nullable
|
||||
T getMapping(final VirtualFile file);
|
||||
T getMapping(VirtualFile file);
|
||||
|
||||
@Nullable
|
||||
T getDefaultMapping(@Nullable VirtualFile file);
|
||||
|
||||
T chosenToStored(final VirtualFile file, final T value);
|
||||
T chosenToStored(VirtualFile file, T value);
|
||||
|
||||
boolean isSelectable(final T value);
|
||||
boolean isSelectable(T value);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.lang;
|
||||
|
||||
import com.intellij.injected.editor.VirtualFileWindow;
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.roots.impl.FilePropertyPusher;
|
||||
import com.intellij.openapi.roots.impl.PushedFilePropertiesUpdater;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author gregsh
|
||||
*/
|
||||
public abstract class PerFileMappingsBase<T> implements PersistentStateComponent<Element>, PerFileMappings<T> {
|
||||
private final Map<VirtualFile, T> myMappings = ContainerUtil.newHashMap();
|
||||
|
||||
@Nullable
|
||||
protected FilePropertyPusher<T> getFilePropertyPusher() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected Project getProject() { return null; }
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<VirtualFile, T> getMappings() {
|
||||
synchronized (myMappings) {
|
||||
cleanup();
|
||||
return Collections.unmodifiableMap(myMappings);
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanup() {
|
||||
for (final VirtualFile file : new ArrayList<VirtualFile>(myMappings.keySet())) {
|
||||
if (file != null //PROJECT, top-level
|
||||
&& !file.isValid()) {
|
||||
myMappings.remove(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public T getMapping(@Nullable VirtualFile file) {
|
||||
FilePropertyPusher<T> pusher = getFilePropertyPusher();
|
||||
T t = getMappingInner(file, myMappings, pusher == null? null : pusher.getFileDataKey());
|
||||
return t == null? getDefaultMapping(file) : t;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected static <T> T getMappingInner(@Nullable VirtualFile file, @Nullable Map<VirtualFile, T> mappings, @Nullable Key<T> pusherKey) {
|
||||
if (file instanceof VirtualFileWindow) {
|
||||
final VirtualFileWindow window = (VirtualFileWindow)file;
|
||||
file = window.getDelegate();
|
||||
}
|
||||
VirtualFile originalFile = file instanceof LightVirtualFile ? ((LightVirtualFile)file).getOriginalFile() : null;
|
||||
if (Comparing.equal(originalFile, file)) originalFile = null;
|
||||
|
||||
if (file != null) {
|
||||
final T pushedValue = pusherKey == null? null : file.getUserData(pusherKey);
|
||||
if (pushedValue != null) return pushedValue;
|
||||
}
|
||||
if (originalFile != null) {
|
||||
final T pushedValue = pusherKey == null? null : originalFile.getUserData(pusherKey);
|
||||
if (pushedValue != null) return pushedValue;
|
||||
}
|
||||
if (mappings == null) return null;
|
||||
synchronized (mappings) {
|
||||
for (VirtualFile cur = file; ; cur = cur.getParent()) {
|
||||
T t = mappings.get(cur);
|
||||
if (t != null) return t;
|
||||
if (originalFile != null) {
|
||||
t = mappings.get(originalFile);
|
||||
if (t != null) return t;
|
||||
originalFile = originalFile.getParent();
|
||||
}
|
||||
if (cur == null) break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T chosenToStored(VirtualFile file, T value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelectable(T value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public T getDefaultMapping(@Nullable VirtualFile file) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T getImmediateMapping(@Nullable VirtualFile file) {
|
||||
synchronized (myMappings) {
|
||||
return myMappings.get(file);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMappings(@NotNull final Map<VirtualFile, T> mappings) {
|
||||
Collection<VirtualFile> oldFiles;
|
||||
synchronized (myMappings) {
|
||||
oldFiles = ContainerUtil.newArrayList(myMappings.keySet());
|
||||
myMappings.clear();
|
||||
myMappings.putAll(mappings);
|
||||
cleanup();
|
||||
}
|
||||
Project project = getProject();
|
||||
handleMappingChange(mappings.keySet(), oldFiles, project != null && !project.isDefault());
|
||||
}
|
||||
|
||||
public void setMapping(@Nullable final VirtualFile file, @Nullable T dialect) {
|
||||
synchronized (myMappings) {
|
||||
if (dialect == null) {
|
||||
myMappings.remove(file);
|
||||
}
|
||||
else {
|
||||
myMappings.put(file, dialect);
|
||||
}
|
||||
}
|
||||
List<VirtualFile> files = ContainerUtil.createMaybeSingletonList(file);
|
||||
handleMappingChange(files, files, false);
|
||||
}
|
||||
|
||||
private void handleMappingChange(Collection<VirtualFile> files, Collection<VirtualFile> oldFiles, boolean includeOpenFiles) {
|
||||
Project project = getProject();
|
||||
FilePropertyPusher<T> pusher = getFilePropertyPusher();
|
||||
if (project != null && pusher != null) {
|
||||
for (VirtualFile oldFile : oldFiles) {
|
||||
if (oldFile == null) continue; // project
|
||||
oldFile.putUserData(pusher.getFileDataKey(), null);
|
||||
}
|
||||
PushedFilePropertiesUpdater updater = PushedFilePropertiesUpdater.getInstance(project);
|
||||
updater.pushAll(pusher);
|
||||
}
|
||||
if (shouldReparseFiles()) {
|
||||
Project[] projects = project == null ? ProjectManager.getInstance().getOpenProjects() : new Project[] { project };
|
||||
for (Project p : projects) {
|
||||
PsiDocumentManager.getInstance(p).reparseFiles(files, includeOpenFiles);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<T> getAvailableValues(VirtualFile file) {
|
||||
return getAvailableValues();
|
||||
}
|
||||
|
||||
protected abstract List<T> getAvailableValues();
|
||||
|
||||
@Nullable
|
||||
protected abstract String serialize(T t);
|
||||
|
||||
@Override
|
||||
public Element getState() {
|
||||
synchronized (myMappings) {
|
||||
cleanup();
|
||||
final Element element = new Element("x");
|
||||
final List<VirtualFile> files = new ArrayList<VirtualFile>(myMappings.keySet());
|
||||
Collections.sort(files, new Comparator<VirtualFile>() {
|
||||
@Override
|
||||
public int compare(final VirtualFile o1, final VirtualFile o2) {
|
||||
if (o1 == null || o2 == null) return o1 == null ? o2 == null ? 0 : 1 : -1;
|
||||
return o1.getPath().compareTo(o2.getPath());
|
||||
}
|
||||
});
|
||||
for (VirtualFile file : files) {
|
||||
final T dialect = myMappings.get(file);
|
||||
String value = serialize(dialect);
|
||||
if (value != null) {
|
||||
final Element child = new Element("file");
|
||||
element.addContent(child);
|
||||
child.setAttribute("url", file == null ? "PROJECT" : file.getUrl());
|
||||
child.setAttribute(getValueAttribute(), value);
|
||||
}
|
||||
}
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected T handleUnknownMapping(VirtualFile file, String value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected String getValueAttribute() {
|
||||
return "value";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(final Element state) {
|
||||
synchronized (myMappings) {
|
||||
final THashMap<String, T> dialectMap = new THashMap<String, T>();
|
||||
for (T dialect : getAvailableValues()) {
|
||||
String key = serialize(dialect);
|
||||
if (key != null) {
|
||||
dialectMap.put(key, dialect);
|
||||
}
|
||||
}
|
||||
final List<Element> files = state.getChildren("file");
|
||||
for (Element fileElement : files) {
|
||||
final String url = fileElement.getAttributeValue("url");
|
||||
final String dialectID = fileElement.getAttributeValue(getValueAttribute());
|
||||
final VirtualFile file = url.equals("PROJECT") ? null : VirtualFileManager.getInstance().findFileByUrl(url);
|
||||
T dialect = dialectMap.get(dialectID);
|
||||
if (dialect == null) {
|
||||
dialect = handleUnknownMapping(file, dialectID);
|
||||
if (dialect == null) continue;
|
||||
}
|
||||
if (file != null || url.equals("PROJECT")) {
|
||||
myMappings.put(file, dialect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public void cleanupForNextTest() {
|
||||
synchronized (myMappings) {
|
||||
myMappings.clear();
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean shouldReparseFiles() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean hasMappings() {
|
||||
synchronized (myMappings) {
|
||||
return !myMappings.isEmpty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,11 +45,7 @@ import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileFilter;
|
||||
import com.intellij.openapi.vfs.ex.temp.TempFileSystem;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ReflectionUtil;
|
||||
import com.intellij.util.ThrowableRunnable;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.io.ZipUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
@@ -68,8 +64,6 @@ import javax.swing.tree.TreePath;
|
||||
import java.awt.*;
|
||||
import java.awt.event.InvocationEvent;
|
||||
import java.io.*;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
@@ -837,20 +831,7 @@ public class PlatformTestUtil {
|
||||
}
|
||||
|
||||
public static void tryGcSoftlyReachableObjects() {
|
||||
ReferenceQueue<Object> q = new ReferenceQueue<Object>();
|
||||
SoftReference<Object> ref = new SoftReference<Object>(new Object(), q);
|
||||
List<Object> list = ContainerUtil.newArrayListWithCapacity(100 + useReference(ref));
|
||||
for (int i = 0; i < 100; i++) {
|
||||
if (q.poll() != null) {
|
||||
break;
|
||||
}
|
||||
list.add(new SoftReference<byte[]>(new byte[(int)Runtime.getRuntime().freeMemory() / 2]));
|
||||
}
|
||||
}
|
||||
|
||||
private static int useReference(SoftReference<Object> ref) {
|
||||
Object o = ref.get();
|
||||
return o == null ? 0 : Math.abs(o.hashCode()) % 10;
|
||||
GCUtil.tryGcSoftlyReachableObjects();
|
||||
}
|
||||
|
||||
public static void withEncoding(@NotNull String encoding, @NotNull final Runnable r) {
|
||||
|
||||
+5
-3
@@ -274,7 +274,7 @@ public interface CodeInsightTestFixture extends IdeaProjectTestFixture {
|
||||
* @return duration
|
||||
*/
|
||||
long checkHighlighting(boolean checkWarnings, boolean checkInfos, boolean checkWeakWarnings);
|
||||
|
||||
|
||||
long checkHighlighting(boolean checkWarnings, boolean checkInfos, boolean checkWeakWarnings, boolean ignoreExtraHighlighting);
|
||||
|
||||
long checkHighlighting();
|
||||
@@ -356,7 +356,7 @@ public interface CodeInsightTestFixture extends IdeaProjectTestFixture {
|
||||
*
|
||||
* @param hint the text that the intention text should begin with.
|
||||
* @return the matching intention
|
||||
* @throws java.lang.AssertionError if no intentions are found or if multiple intentions match the hint text.
|
||||
* @throws java.lang.AssertionError if no intentions are found or if multiple intentions match the hint text.
|
||||
*/
|
||||
IntentionAction findSingleIntention(@NotNull String hint);
|
||||
|
||||
@@ -561,9 +561,11 @@ public interface CodeInsightTestFixture extends IdeaProjectTestFixture {
|
||||
* Actually, it works just like {@link #completeBasic()} but supports
|
||||
* several {@link #CARET_MARKER}
|
||||
*
|
||||
* @return list of all completion elements just like in {@link #completeBasic()}
|
||||
* @see #completeBasic()
|
||||
*/
|
||||
void completeBasicAllCarets();
|
||||
@NotNull
|
||||
List<LookupElement> completeBasicAllCarets();
|
||||
|
||||
void saveText(VirtualFile file, String text);
|
||||
}
|
||||
|
||||
+8
-2
@@ -1068,7 +1068,8 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
|
||||
|
||||
|
||||
@Override
|
||||
public void completeBasicAllCarets() {
|
||||
@NotNull
|
||||
public final List<LookupElement> completeBasicAllCarets() {
|
||||
final CaretModel caretModel = myEditor.getCaretModel();
|
||||
final List<Caret> carets = caretModel.getAllCarets();
|
||||
|
||||
@@ -1082,10 +1083,15 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
|
||||
// We do it in reverse order because completions would affect offsets
|
||||
// i.e.: when you complete "spa" to "spam", next caret offset increased by 1
|
||||
Collections.reverse(originalOffsets);
|
||||
final List<LookupElement> result = new ArrayList<LookupElement>();
|
||||
for (final int originalOffset : originalOffsets) {
|
||||
caretModel.moveToOffset(originalOffset);
|
||||
completeBasic();
|
||||
final LookupElement[] lookupElements = completeBasic();
|
||||
if (lookupElements != null) {
|
||||
result.addAll(Arrays.asList(lookupElements));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.util;
|
||||
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
public class GCUtil {
|
||||
public static void tryForceGC() {
|
||||
tryGcSoftlyReachableObjects();
|
||||
WeakReference<Object> weakReference = new WeakReference<Object>(new Object());
|
||||
do {
|
||||
System.gc();
|
||||
}
|
||||
while (weakReference.get() != null);
|
||||
}
|
||||
|
||||
public static void tryGcSoftlyReachableObjects() {
|
||||
ReferenceQueue<Object> q = new ReferenceQueue<Object>();
|
||||
SoftReference<Object> ref = new SoftReference<Object>(new Object(), q);
|
||||
List<Object> list = ContainerUtil.newArrayListWithCapacity(100 + useReference(ref));
|
||||
for (int i = 0; i < 100; i++) {
|
||||
if (q.poll() != null) {
|
||||
break;
|
||||
}
|
||||
list.add(new SoftReference<byte[]>(new byte[(int)Runtime.getRuntime().freeMemory() / 2]));
|
||||
}
|
||||
}
|
||||
|
||||
private static int useReference(SoftReference<Object> ref) {
|
||||
Object o = ref.get();
|
||||
return o == null ? 0 : Math.abs(o.hashCode()) % 10;
|
||||
}
|
||||
}
|
||||
@@ -3215,10 +3215,6 @@ public class UIUtil {
|
||||
textComponent.getActionMap().put("redoKeystroke", REDO_ACTION);
|
||||
}
|
||||
|
||||
public static void adjustRows(JTextArea area, int minRows, int maxRows) {
|
||||
area.setRows(Math.max(minRows, Math.min(maxRows, area.getText().split("\n").length)));
|
||||
}
|
||||
|
||||
public static void playSoundFromResource(final String resourceName) {
|
||||
final Class callerClass = ReflectionUtil.getGrandCallerClass();
|
||||
if (callerClass == null) return;
|
||||
|
||||
@@ -16,11 +16,10 @@
|
||||
package com.intellij.util.containers;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.GCUtil;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -96,12 +95,7 @@ public class ConcurrentMapsTest {
|
||||
}
|
||||
|
||||
public static void tryGcSoftlyReachableObjects() {
|
||||
SoftReference<?> reference = new SoftReference<Object>(new Object());
|
||||
List<Object> list = ContainerUtil.newArrayList();
|
||||
while (reference.get() != null) {
|
||||
int chunk = (int)Math.min(Runtime.getRuntime().freeMemory() / 2, Integer.MAX_VALUE);
|
||||
list.add(new SoftReference<byte[]>(new byte[chunk]));
|
||||
}
|
||||
GCUtil.tryGcSoftlyReachableObjects();
|
||||
}
|
||||
|
||||
@Test(timeout = TIMEOUT)
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
*/
|
||||
package com.intellij.util.containers;
|
||||
|
||||
import com.intellij.util.GCUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -225,11 +225,6 @@ public class WeakListTest {
|
||||
}
|
||||
|
||||
private static void gc() {
|
||||
ConcurrentMapsTest.tryGcSoftlyReachableObjects();
|
||||
WeakReference<Object> weakReference = new WeakReference<Object>(new Object());
|
||||
do {
|
||||
System.gc();
|
||||
}
|
||||
while (weakReference.get() != null);
|
||||
GCUtil.tryForceGC();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ import com.intellij.vcs.log.data.VcsLogDataHolder;
|
||||
import com.intellij.vcs.log.data.VisiblePack;
|
||||
import com.intellij.vcs.log.graph.ColorGenerator;
|
||||
import com.intellij.vcs.log.graph.PrintElement;
|
||||
import com.intellij.vcs.log.graph.RowInfo;
|
||||
import com.intellij.vcs.log.graph.RowType;
|
||||
import com.intellij.vcs.log.graph.actions.GraphAnswer;
|
||||
import com.intellij.vcs.log.graph.actions.GraphMouseAction;
|
||||
import com.intellij.vcs.log.printer.idea.GraphCellPainter;
|
||||
@@ -321,16 +323,17 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C
|
||||
}
|
||||
|
||||
public void applyHighlighters(@NotNull Component rendererComponent, int row, boolean selected) {
|
||||
RowInfo<Integer> rowInfo = myDataPack.getVisibleGraph().getRowInfo(row);
|
||||
boolean fgUpdated = false;
|
||||
for (VcsLogHighlighter highlighter : myHighlighters) {
|
||||
Color color = highlighter.getForeground(myDataPack.getVisibleGraph().getRowInfo(row).getCommit(), selected);
|
||||
Color color = highlighter.getForeground(rowInfo.getCommit(), selected);
|
||||
if (color != null) {
|
||||
rendererComponent.setForeground(color);
|
||||
fgUpdated = true;
|
||||
}
|
||||
}
|
||||
if (!fgUpdated) { // reset highlighting if no-one wants to change it
|
||||
rendererComponent.setForeground(UIUtil.getTableForeground(selected));
|
||||
rendererComponent.setForeground(rowInfo.getRowType() == RowType.UNMATCHED ? JBColor.GRAY : UIUtil.getTableForeground(selected));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -111,8 +111,10 @@ public class InnerClassMayBeStaticInspection extends BaseInspection {
|
||||
if (argumentList == null) {
|
||||
continue;
|
||||
}
|
||||
final PsiExpression expression =
|
||||
factory.createExpressionFromText("new " + classReference.getQualifiedName() + argumentList.getText(), innerClass);
|
||||
final PsiReferenceParameterList parameterList = classReference.getParameterList();
|
||||
final String genericParameters = parameterList != null ? parameterList.getText() : "";
|
||||
final PsiExpression expression = factory
|
||||
.createExpressionFromText("new " + classReference.getQualifiedName() + genericParameters + argumentList.getText(), innerClass);
|
||||
codeStyleManager.shortenClassReferences(newExpression.replace(expression));
|
||||
}
|
||||
final PsiModifierList modifiers = innerClass.getModifierList();
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
class IdeaTest {
|
||||
|
||||
public void test(){
|
||||
print(new InnerClass<Integer>().foo(Integer.valueOf(1)));
|
||||
}
|
||||
|
||||
public void print(Integer foo){
|
||||
System.out.println(foo);
|
||||
}
|
||||
|
||||
static class InnerClass<T>{
|
||||
public T foo(T bar){
|
||||
return bar;
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
class IdeaTest {
|
||||
|
||||
public void test(){
|
||||
print(new InnerClass<Integer>().foo(Integer.valueOf(1)));
|
||||
}
|
||||
|
||||
public void print(Integer foo){
|
||||
System.out.println(foo);
|
||||
}
|
||||
|
||||
class Inn<caret>erClass<T>{
|
||||
public T foo(T bar){
|
||||
return bar;
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-4
@@ -33,8 +33,6 @@ public class InnerClassMayBeStaticFixTest extends IGQuickFixesTestCase {
|
||||
}
|
||||
|
||||
public void testSimple() { doTest(); }
|
||||
|
||||
public void testAnonymousInside() {
|
||||
doTest();
|
||||
}
|
||||
public void testAnonymousInside() { doTest(); }
|
||||
public void testPreserveGenericSignature() { doTest(); }
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -149,27 +149,8 @@ public class IdeaJdk extends JavaDependentSdkType implements JavaSdkType {
|
||||
}
|
||||
|
||||
public String suggestSdkName(String currentSdkName, String sdkHome) {
|
||||
@NonNls final String productName;
|
||||
if (new File(sdkHome, "lib/rubymine.jar").exists()) {
|
||||
productName = "RubyMine ";
|
||||
}
|
||||
else if (new File(sdkHome, "lib/pycharm.jar").exists()) {
|
||||
productName = "PyCharm ";
|
||||
}
|
||||
else if (new File(sdkHome, "lib/webide.jar").exists()) {
|
||||
productName = "WebStorm/PhpStorm ";
|
||||
}
|
||||
else if (new File(sdkHome, "license/AppCode_license.txt").exists()) {
|
||||
productName = "AppCode ";
|
||||
}
|
||||
else if (new File(sdkHome, "license/CLion_Preview_License.txt").exists()) {
|
||||
productName = "CLion ";
|
||||
}
|
||||
else {
|
||||
productName = "IDEA ";
|
||||
}
|
||||
String buildNumber = getBuildNumber(sdkHome);
|
||||
return productName + (buildNumber != null ? buildNumber : "");
|
||||
return IntelliJPlatformProduct.fromBuildNumber(buildNumber).getName() + " " + (buildNumber != null ? buildNumber : "");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.idea.devkit.projectRoots;
|
||||
|
||||
import com.intellij.util.PlatformUtils;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public enum IntelliJPlatformProduct {
|
||||
IDEA("IU", "IntelliJ IDEA", null),
|
||||
IDEA_IC("IC", "IntelliJ IDEA Community Edition", PlatformUtils.IDEA_CE_PREFIX),
|
||||
RUBYMINE("RM", "RubyMine", PlatformUtils.RUBY_PREFIX),
|
||||
PYCHARM("PY", "PyCharm", PlatformUtils.PYCHARM_PREFIX),
|
||||
PYCHARM_PC("PC", "PyCharm Community Edition", PlatformUtils.PYCHARM_CE_PREFIX),
|
||||
PYCHARM_EDU("PE", "PyCharm Educational Edition", PlatformUtils.PYCHARM_EDU_PREFIX),
|
||||
PHPSTORM("PS", "PhpStorm", PlatformUtils.PHP_PREFIX),
|
||||
WEBSTORM("WS", "WebStorm", PlatformUtils.WEB_PREFIX),
|
||||
APPCODE("OC", "AppCode", PlatformUtils.APPCODE_PREFIX),
|
||||
CLION("CL", "CLion", PlatformUtils.CLION_PREFIX),
|
||||
DBE("DB", "0xDBE", PlatformUtils.DBE_PREFIX),
|
||||
ANDROID_STUDIO("AI", "Android Studio", "AndroidStudio");
|
||||
|
||||
private String myProductCode;
|
||||
private String myName;
|
||||
private String myPlatformPrefix;
|
||||
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
public String getPlatformPrefix() {
|
||||
return myPlatformPrefix;
|
||||
}
|
||||
|
||||
IntelliJPlatformProduct(String productCode, String name, String platformPrefix) {
|
||||
myProductCode = productCode;
|
||||
myName = name;
|
||||
myPlatformPrefix = platformPrefix;
|
||||
}
|
||||
|
||||
public static IntelliJPlatformProduct fromBuildNumber(String buildNumber) {
|
||||
for (IntelliJPlatformProduct product : values()) {
|
||||
if (buildNumber.startsWith(product.myProductCode)) {
|
||||
return product;
|
||||
}
|
||||
}
|
||||
return IDEA;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,12 +15,10 @@
|
||||
*/
|
||||
package org.jetbrains.idea.devkit.run;
|
||||
|
||||
import com.google.common.io.PatternFilenameFilter;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -30,59 +28,22 @@ import java.io.IOException;
|
||||
* Date: Dec 3, 2004
|
||||
*/
|
||||
public class IdeaLicenseHelper {
|
||||
@NonNls private static final String LICENSE_PATH_PREFERRED = "idea80.key";
|
||||
@NonNls private static final String LICENSE_PATH_70 = "idea70.key";
|
||||
@NonNls private static final String LICENSE_PATH_60 = "idea60.key";
|
||||
@NonNls private static final String LICENSE_PATH_50 = "idea50.key";
|
||||
@NonNls private static final String LICENSE_PATH_40 = "idea40.key";
|
||||
@NonNls private static final String LICENSE_PATH_SYSTEM = "idea.license";
|
||||
|
||||
@NonNls private static final String CONFIG_DIR_NAME = "config";
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.devkit.run.IdeaLicenseHelper");
|
||||
|
||||
@Nullable
|
||||
public static File isIDEALicenseInSandbox(@NonNls final String configPath, @NonNls final String systemPath, @NonNls final String binPath){
|
||||
final File config = new File(configPath, LICENSE_PATH_PREFERRED);
|
||||
if (config.exists()){
|
||||
return config;
|
||||
}
|
||||
final File idea70 = new File(configPath, LICENSE_PATH_70);
|
||||
if (idea70.exists()){
|
||||
return idea70;
|
||||
}
|
||||
final File idea60 = new File(configPath, LICENSE_PATH_60);
|
||||
if (idea60.exists()){
|
||||
return idea60;
|
||||
}
|
||||
final File idea5 = new File(configPath, LICENSE_PATH_50);
|
||||
if (idea5.exists()){
|
||||
return idea5;
|
||||
}
|
||||
final File idea4 = new File(configPath, LICENSE_PATH_40);
|
||||
if (idea4.exists()){
|
||||
return idea4;
|
||||
}
|
||||
final File system = new File(systemPath, LICENSE_PATH_SYSTEM);
|
||||
if (system.exists()){
|
||||
return system;
|
||||
}
|
||||
final File bin = new File(binPath, LICENSE_PATH_SYSTEM);
|
||||
if (bin.exists()){
|
||||
return bin;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void copyIDEALicense(final String sandboxHome, Sdk jdk){
|
||||
if (isIDEALicenseInSandbox(sandboxHome + File.separator + CONFIG_DIR_NAME, sandboxHome + File.separator + "system", jdk.getHomePath() + File.separator + "bin") == null){
|
||||
final File ideaLicense = isIDEALicenseInSandbox(PathManager.getConfigPath(), PathManager.getSystemPath(), PathManager.getBinPath());
|
||||
if (ideaLicense != null){
|
||||
try {
|
||||
FileUtil.copy(ideaLicense, new File(new File(sandboxHome, CONFIG_DIR_NAME), LICENSE_PATH_PREFERRED));
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
public static void copyIDEALicense(final String sandboxHome) {
|
||||
File sandboxSystemPath = new File(sandboxHome, "system");
|
||||
File systemPath = new File(PathManager.getSystemPath());
|
||||
File[] runningIdeaLicenses = systemPath.listFiles(new PatternFilenameFilter("idea\\d+\\.key"));
|
||||
if (runningIdeaLicenses != null) {
|
||||
for (File license : runningIdeaLicenses) {
|
||||
File devIdeaLicense = new File(sandboxSystemPath, license.getName());
|
||||
if (!devIdeaLicense.exists()) {
|
||||
try {
|
||||
FileUtil.copy(license, devIdeaLicense);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -38,6 +38,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.devkit.DevKitBundle;
|
||||
import org.jetbrains.idea.devkit.projectRoots.IdeaJdk;
|
||||
import org.jetbrains.idea.devkit.projectRoots.IntelliJPlatformProduct;
|
||||
import org.jetbrains.idea.devkit.projectRoots.Sandbox;
|
||||
|
||||
import java.io.File;
|
||||
@@ -97,7 +98,7 @@ public class PluginRunConfiguration extends RunConfigurationBase implements Modu
|
||||
final String canonicalSandbox = sandboxHome;
|
||||
|
||||
//copy license from running instance of idea
|
||||
IdeaLicenseHelper.copyIDEALicense(sandboxHome, ideaJdk);
|
||||
IdeaLicenseHelper.copyIDEALicense(sandboxHome);
|
||||
|
||||
final JavaCommandLineState state = new JavaCommandLineState(env) {
|
||||
@Override
|
||||
@@ -141,37 +142,9 @@ public class PluginRunConfiguration extends RunConfigurationBase implements Modu
|
||||
|
||||
if (!vm.hasProperty(PlatformUtils.PLATFORM_PREFIX_KEY)) {
|
||||
String buildNumber = IdeaJdk.getBuildNumber(usedIdeaJdk.getHomePath());
|
||||
|
||||
if (buildNumber != null) {
|
||||
String prefix = null;
|
||||
|
||||
if (buildNumber.startsWith("IC")) {
|
||||
prefix = PlatformUtils.IDEA_CE_PREFIX;
|
||||
}
|
||||
else if (buildNumber.startsWith("PY")) {
|
||||
prefix = PlatformUtils.PYCHARM_PREFIX;
|
||||
}
|
||||
else if (buildNumber.startsWith("PC")) {
|
||||
prefix = PlatformUtils.PYCHARM_CE_PREFIX;
|
||||
}
|
||||
else if (buildNumber.startsWith("RM")) {
|
||||
prefix = PlatformUtils.RUBY_PREFIX;
|
||||
}
|
||||
else if (buildNumber.startsWith("PS")) {
|
||||
prefix = PlatformUtils.PHP_PREFIX;
|
||||
}
|
||||
else if (buildNumber.startsWith("WS")) {
|
||||
prefix = PlatformUtils.WEB_PREFIX;
|
||||
}
|
||||
else if (buildNumber.startsWith("OC")) {
|
||||
prefix = PlatformUtils.APPCODE_PREFIX;
|
||||
}
|
||||
else if (buildNumber.startsWith("CL")) {
|
||||
prefix = PlatformUtils.CLION_PREFIX;
|
||||
}
|
||||
else if (buildNumber.startsWith("DB")) {
|
||||
prefix = PlatformUtils.DBE_PREFIX;
|
||||
}
|
||||
|
||||
String prefix = IntelliJPlatformProduct.fromBuildNumber(buildNumber).getPlatformPrefix();
|
||||
if (prefix != null) {
|
||||
vm.defineProperty(PlatformUtils.PLATFORM_PREFIX_KEY, prefix);
|
||||
}
|
||||
|
||||
+2
-1
@@ -31,6 +31,7 @@ import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.ui.RowIcon;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -492,7 +493,7 @@ public class GroovyScriptClass extends LightElement implements PsiClass, Synthet
|
||||
|
||||
@Override
|
||||
public PsiElement setName(@NotNull String name) throws IncorrectOperationException {
|
||||
myFile.setName(name + "." + myFile.getViewProvider().getVirtualFile().getExtension());
|
||||
myFile.setName(PathUtil.makeFileName(name, myFile.getViewProvider().getVirtualFile().getExtension()));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -22,12 +22,14 @@ import com.intellij.execution.Executor;
|
||||
import com.intellij.execution.configurations.JavaParameters;
|
||||
import com.intellij.execution.configurations.RunProfile;
|
||||
import com.intellij.execution.runners.ExecutionUtil;
|
||||
import com.intellij.execution.util.ScriptFileUtil;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ui.configuration.ClasspathEditor;
|
||||
import com.intellij.openapi.roots.ui.configuration.ModulesConfigurator;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.encoding.EncodingManager;
|
||||
@@ -77,7 +79,8 @@ public class DefaultGroovyScriptRunner extends GroovyScriptRunner {
|
||||
params.getProgramParametersList().add("--debug");
|
||||
}
|
||||
|
||||
params.getProgramParametersList().add(FileUtil.toSystemDependentName(configuration.getScriptPath()));
|
||||
String path = ScriptFileUtil.getLocalFilePath(StringUtil.notNullize(configuration.getScriptPath()));
|
||||
params.getProgramParametersList().add(FileUtil.toSystemDependentName(path));
|
||||
params.getProgramParametersList().addParametersString(configuration.getScriptParameters());
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -22,6 +22,7 @@ import com.intellij.execution.process.ProcessAdapter;
|
||||
import com.intellij.execution.process.ProcessEvent;
|
||||
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
import com.intellij.execution.util.ProgramParametersUtil;
|
||||
import com.intellij.execution.util.ScriptFileUtil;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.PathMacroManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -37,8 +38,6 @@ import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.JDOMExternalizer;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.psi.PsiClass;
|
||||
@@ -47,8 +46,10 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.refactoring.listeners.RefactoringElementAdapter;
|
||||
import com.intellij.refactoring.listeners.RefactoringElementListener;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.SystemProperties;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.hash.LinkedHashMap;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -175,7 +176,7 @@ public class GroovyScriptRunConfiguration extends ModuleBasedConfiguration<RunCo
|
||||
throw new CantRunException("Unknown script type " + scriptPath);
|
||||
}
|
||||
|
||||
final Module module = getModule();
|
||||
final Module module = ObjectUtils.chooseNotNull(getModule(), ContainerUtil.getFirstItem(getValidModules()));
|
||||
if (!scriptRunner.ensureRunnerConfigured(module, this, executor, getProject())) {
|
||||
return null;
|
||||
}
|
||||
@@ -231,7 +232,7 @@ public class GroovyScriptRunConfiguration extends ModuleBasedConfiguration<RunCo
|
||||
protected void elementRenamedOrMoved(@NotNull PsiElement newElement) {
|
||||
if (newElement instanceof GroovyFile) {
|
||||
GroovyFile file = (GroovyFile)newElement;
|
||||
setScriptPath(file.getVirtualFile().getPath());
|
||||
setScriptPath(ScriptFileUtil.getScriptFilePath(file.getVirtualFile()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,8 +285,7 @@ public class GroovyScriptRunConfiguration extends ModuleBasedConfiguration<RunCo
|
||||
|
||||
@Nullable
|
||||
private VirtualFile getScriptFile() {
|
||||
if (scriptPath == null) return null;
|
||||
return LocalFileSystem.getInstance().findFileByPath(FileUtil.toSystemIndependentName(scriptPath));
|
||||
return ScriptFileUtil.findScriptFileByPath(scriptPath);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+9
-5
@@ -25,8 +25,10 @@ import com.intellij.execution.application.ApplicationConfigurationProducer;
|
||||
import com.intellij.execution.configurations.RunConfiguration;
|
||||
import com.intellij.execution.configurations.RunConfigurationModule;
|
||||
import com.intellij.execution.junit.RuntimeConfigurationProducer;
|
||||
import com.intellij.execution.util.ScriptFileUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -100,7 +102,7 @@ public class GroovyScriptRunConfigurationProducer extends RuntimeConfigurationPr
|
||||
final PsiFile file = location.getPsiElement().getContainingFile();
|
||||
if (file instanceof GroovyFile) {
|
||||
final VirtualFile vfile = file.getVirtualFile();
|
||||
if (vfile != null && FileUtil.toSystemIndependentName(path).equals(vfile.getPath())) {
|
||||
if (vfile != null && FileUtil.toSystemIndependentName(path).equals(ScriptFileUtil.getScriptFilePath(vfile))) {
|
||||
if (!((GroovyFile)file).isScript() ||
|
||||
GroovyScriptUtil.getScriptType((GroovyFile)file).isConfigurationByLocation(existing, location)) {
|
||||
return existingConfiguration;
|
||||
@@ -127,15 +129,17 @@ public class GroovyScriptRunConfigurationProducer extends RuntimeConfigurationPr
|
||||
final GroovyScriptRunConfiguration configuration = (GroovyScriptRunConfiguration)settings.getConfiguration();
|
||||
final PsiFile file = aClass.getContainingFile().getOriginalFile();
|
||||
final PsiDirectory dir = file.getContainingDirectory();
|
||||
if (dir == null) return null;
|
||||
configuration.setWorkDir(dir.getVirtualFile().getPath());
|
||||
if (dir != null) {
|
||||
configuration.setWorkDir(dir.getVirtualFile().getPath());
|
||||
}
|
||||
final VirtualFile vFile = file.getVirtualFile();
|
||||
if (vFile == null) return null;
|
||||
configuration.setScriptPath(vFile.getPath());
|
||||
String path = ScriptFileUtil.getScriptFilePath(vFile);
|
||||
configuration.setScriptPath(path);
|
||||
RunConfigurationModule module = configuration.getConfigurationModule();
|
||||
|
||||
String name = GroovyRunnerUtil.getConfigurationName(aClass, module);
|
||||
configuration.setName(name);
|
||||
configuration.setName(StringUtil.isEmpty(name) ? vFile.getName() : name);
|
||||
configuration.setModule(JavaExecutionUtil.findModule(aClass));
|
||||
return settings;
|
||||
}
|
||||
|
||||
+4
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -112,7 +112,9 @@ public class InvocationExprent extends Exprent {
|
||||
}
|
||||
else {
|
||||
// FIXME: remove the first parameter completely from the list. It's the object type for a virtual lambda method.
|
||||
instance = lstParameters.get(0);
|
||||
if (!lstParameters.isEmpty()) {
|
||||
instance = lstParameters.get(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (opcode == CodeConstants.opc_invokestatic) {
|
||||
|
||||
Binary file not shown.
@@ -1,10 +1,12 @@
|
||||
package pkg;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.IntBinaryOperator;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
@@ -13,179 +15,189 @@ public class TestClassLambda {
|
||||
public int field = 0;
|
||||
|
||||
public void testLambda() {
|
||||
List var1 = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3), Integer.valueOf(4), Integer.valueOf(5), Integer.valueOf(6), Integer.valueOf(7)});// 27
|
||||
int var2 = (int)Math.random();// 28
|
||||
var1.forEach((var2x) -> {// 30
|
||||
List var1 = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3), Integer.valueOf(4), Integer.valueOf(5), Integer.valueOf(6), Integer.valueOf(7)});// 29
|
||||
int var2 = (int)Math.random();// 30
|
||||
var1.forEach((var2x) -> {// 32
|
||||
int var3 = 2 * var2x.intValue();
|
||||
System.out.println(var3 + var2 + this.field);
|
||||
});
|
||||
}
|
||||
|
||||
public void testLambda1() {
|
||||
int var1 = (int)Math.random();// 37
|
||||
int var1 = (int)Math.random();// 39
|
||||
Runnable var2 = () -> {
|
||||
System.out.println("hello1" + var1);
|
||||
};// 38
|
||||
};// 40
|
||||
Runnable var3 = () -> {
|
||||
System.out.println("hello2" + var1);
|
||||
};// 39
|
||||
};// 41
|
||||
}
|
||||
|
||||
public void testLambda2() {
|
||||
reduce((var0, var1) -> {// 43
|
||||
reduce((var0, var1) -> {// 45
|
||||
return Math.max(var0, var1);
|
||||
});
|
||||
}
|
||||
|
||||
public void testLambda3() {
|
||||
reduce(Math::max);// 47
|
||||
reduce(Math::max);// 49
|
||||
}
|
||||
|
||||
public void testLambda4() {
|
||||
reduce(TestClassLambda::localMax);// 51
|
||||
reduce(TestClassLambda::localMax);// 53
|
||||
}
|
||||
|
||||
public void testLambda5() {
|
||||
String var1 = "abcd";// 55
|
||||
function(var1::toString);// 56
|
||||
String var1 = "abcd";// 57
|
||||
function(var1::toString);// 58
|
||||
}
|
||||
|
||||
public void testLambda6() {
|
||||
ArrayList var1 = new ArrayList();// 60
|
||||
int var2 = var1.size() * 2;// 61
|
||||
int var3 = var1.size() * 5;// 62
|
||||
var1.removeIf((var2x) -> {// 63
|
||||
ArrayList var1 = new ArrayList();// 62
|
||||
int var2 = var1.size() * 2;// 63
|
||||
int var3 = var1.size() * 5;// 64
|
||||
var1.removeIf((var2x) -> {// 65
|
||||
return var2 >= var2x.length() && var2x.length() <= var3;
|
||||
});
|
||||
}
|
||||
|
||||
public static void testLambda7(Annotation[] var0) {
|
||||
Arrays.stream(var0).map(Annotation::annotationType);// 69
|
||||
}
|
||||
|
||||
public static OptionalInt reduce(IntBinaryOperator var0) {
|
||||
return null;// 67
|
||||
return null;// 73
|
||||
}
|
||||
|
||||
public static String function(Supplier<String> var0) {
|
||||
return (String)var0.get();// 71
|
||||
return (String)var0.get();// 77
|
||||
}
|
||||
|
||||
public static int localMax(int var0, int var1) {
|
||||
return 0;// 75
|
||||
return 0;// 81
|
||||
}
|
||||
|
||||
public void nestedLambdas() {
|
||||
byte var1 = 5;// 79
|
||||
byte var1 = 5;// 85
|
||||
Runnable var2 = () -> {
|
||||
Runnable var1x = () -> {
|
||||
System.out.println("hello2" + var1);
|
||||
};
|
||||
System.out.println("hello1" + var1);
|
||||
};// 80
|
||||
};// 86
|
||||
}
|
||||
}
|
||||
|
||||
class 'pkg/TestClassLambda' {
|
||||
method 'testLambda ()V' {
|
||||
7 15
|
||||
8 15
|
||||
e 15
|
||||
f 15
|
||||
15 15
|
||||
16 15
|
||||
1c 15
|
||||
1d 15
|
||||
23 15
|
||||
24 15
|
||||
2a 15
|
||||
2c 15
|
||||
33 15
|
||||
35 15
|
||||
39 15
|
||||
3c 15
|
||||
3d 16
|
||||
40 16
|
||||
41 16
|
||||
4a 17
|
||||
7 17
|
||||
8 17
|
||||
e 17
|
||||
f 17
|
||||
15 17
|
||||
16 17
|
||||
1c 17
|
||||
1d 17
|
||||
23 17
|
||||
24 17
|
||||
2a 17
|
||||
2c 17
|
||||
33 17
|
||||
35 17
|
||||
39 17
|
||||
3c 17
|
||||
3d 18
|
||||
40 18
|
||||
41 18
|
||||
4a 19
|
||||
}
|
||||
|
||||
method 'testLambda1 ()V' {
|
||||
0 24
|
||||
3 24
|
||||
4 24
|
||||
b 27
|
||||
12 30
|
||||
0 26
|
||||
3 26
|
||||
4 26
|
||||
b 29
|
||||
12 32
|
||||
}
|
||||
|
||||
method 'testLambda2 ()V' {
|
||||
5 34
|
||||
5 36
|
||||
}
|
||||
|
||||
method 'testLambda3 ()V' {
|
||||
5 40
|
||||
5 42
|
||||
}
|
||||
|
||||
method 'testLambda4 ()V' {
|
||||
5 44
|
||||
5 46
|
||||
}
|
||||
|
||||
method 'testLambda5 ()V' {
|
||||
0 48
|
||||
2 48
|
||||
e 49
|
||||
0 50
|
||||
2 50
|
||||
e 51
|
||||
}
|
||||
|
||||
method 'testLambda6 ()V' {
|
||||
7 53
|
||||
9 54
|
||||
e 54
|
||||
f 54
|
||||
10 54
|
||||
12 55
|
||||
17 55
|
||||
18 55
|
||||
19 55
|
||||
22 56
|
||||
7 55
|
||||
9 56
|
||||
e 56
|
||||
f 56
|
||||
10 56
|
||||
12 57
|
||||
17 57
|
||||
18 57
|
||||
19 57
|
||||
22 58
|
||||
}
|
||||
|
||||
method 'testLambda7 ([Ljava/lang/annotation/Annotation;)V' {
|
||||
1 64
|
||||
9 64
|
||||
}
|
||||
|
||||
method 'reduce (Ljava/util/function/IntBinaryOperator;)Ljava/util/OptionalInt;' {
|
||||
0 62
|
||||
1 62
|
||||
0 68
|
||||
1 68
|
||||
}
|
||||
|
||||
method 'function (Ljava/util/function/Supplier;)Ljava/lang/String;' {
|
||||
1 66
|
||||
6 66
|
||||
9 66
|
||||
1 72
|
||||
6 72
|
||||
9 72
|
||||
}
|
||||
|
||||
method 'localMax (II)I' {
|
||||
0 70
|
||||
1 70
|
||||
0 76
|
||||
1 76
|
||||
}
|
||||
|
||||
method 'nestedLambdas ()V' {
|
||||
0 74
|
||||
1 74
|
||||
8 80
|
||||
0 80
|
||||
1 80
|
||||
8 86
|
||||
}
|
||||
}
|
||||
|
||||
Lines mapping:
|
||||
27 <-> 16
|
||||
28 <-> 17
|
||||
30 <-> 18
|
||||
37 <-> 25
|
||||
38 <-> 28
|
||||
39 <-> 31
|
||||
43 <-> 35
|
||||
47 <-> 41
|
||||
51 <-> 45
|
||||
55 <-> 49
|
||||
56 <-> 50
|
||||
60 <-> 54
|
||||
61 <-> 55
|
||||
29 <-> 18
|
||||
30 <-> 19
|
||||
32 <-> 20
|
||||
39 <-> 27
|
||||
40 <-> 30
|
||||
41 <-> 33
|
||||
45 <-> 37
|
||||
49 <-> 43
|
||||
53 <-> 47
|
||||
57 <-> 51
|
||||
58 <-> 52
|
||||
62 <-> 56
|
||||
63 <-> 57
|
||||
67 <-> 63
|
||||
71 <-> 67
|
||||
75 <-> 71
|
||||
79 <-> 75
|
||||
80 <-> 81
|
||||
64 <-> 58
|
||||
65 <-> 59
|
||||
69 <-> 65
|
||||
73 <-> 69
|
||||
77 <-> 73
|
||||
81 <-> 77
|
||||
85 <-> 81
|
||||
86 <-> 87
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
*/
|
||||
package pkg;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.IntBinaryOperator;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -63,6 +65,10 @@ public class TestClassLambda {
|
||||
list.removeIf(s -> (bottom >= s.length() && s.length() <= top));
|
||||
}
|
||||
|
||||
public static void testLambda7(Annotation[] annotations) {
|
||||
Arrays.stream(annotations).map(Annotation::annotationType);
|
||||
}
|
||||
|
||||
public static OptionalInt reduce(IntBinaryOperator op) {
|
||||
return null;
|
||||
}
|
||||
|
||||
+2
-19
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,7 +24,6 @@ import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.registry.RegistryValue;
|
||||
@@ -38,12 +37,10 @@ import com.intellij.testFramework.PlatformTestUtil;
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.ThrowableRunnable;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.io.URLUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Set;
|
||||
|
||||
public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase {
|
||||
@Override
|
||||
@@ -79,7 +76,7 @@ public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase {
|
||||
if (file.isDirectory()) {
|
||||
System.out.println(file.getPath());
|
||||
}
|
||||
else if (file.getFileType() == StdFileTypes.CLASS && !file.getName().contains("$") && !skip(file)) {
|
||||
else if (file.getFileType() == StdFileTypes.CLASS && !file.getName().contains("$")) {
|
||||
PsiFile clsFile = getPsiManager().findFile(file);
|
||||
assertNotNull(file.getPath(), clsFile);
|
||||
PsiElement mirror = ((ClsFileImpl)clsFile).getMirror();
|
||||
@@ -97,20 +94,6 @@ public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean skip(VirtualFile file) {
|
||||
if (!SystemInfo.isJavaVersionAtLeast("1.8")) return false;
|
||||
String path = file.getPath();
|
||||
int p = path.indexOf("!/");
|
||||
return p > 0 && knowProblems.contains(path.substring(p + 2));
|
||||
}
|
||||
|
||||
// todo[r.sh] drop when IDEA-129734 get fixed
|
||||
private final Set<String> knowProblems = ContainerUtil.newHashSet(
|
||||
"java/lang/reflect/AnnotatedElement.class", "java/util/stream/Nodes.class", "java/util/stream/FindOps.class",
|
||||
"java/util/stream/Collectors.class", "java/util/stream/DistinctOps.class", "java/util/stream/IntPipeline.class",
|
||||
"java/util/stream/LongPipeline.class", "java/util/stream/DoublePipeline.class"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -20,12 +20,10 @@ import com.intellij.lang.properties.PropertiesBundle;
|
||||
import com.intellij.lang.properties.ResourceBundle;
|
||||
import com.intellij.lang.properties.psi.PropertiesFile;
|
||||
import com.intellij.lang.properties.structureView.PropertiesPrefixGroup;
|
||||
import com.intellij.openapi.actionSystem.ActionPlaces;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.FileEditor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.InputValidator;
|
||||
@@ -55,11 +53,15 @@ class NewPropertyAction extends AnAction {
|
||||
if (project == null) {
|
||||
return;
|
||||
}
|
||||
final FileEditor editor = PlatformDataKeys.FILE_EDITOR.getData(e.getDataContext());
|
||||
if (editor == null || !(editor instanceof ResourceBundleEditor)) {
|
||||
return;
|
||||
final ResourceBundleEditor resourceBundleEditor;
|
||||
final DataContext context = e.getDataContext();
|
||||
FileEditor fileEditor = PlatformDataKeys.FILE_EDITOR.getData(context);
|
||||
if (fileEditor instanceof ResourceBundleEditor) {
|
||||
resourceBundleEditor = (ResourceBundleEditor)fileEditor;
|
||||
} else {
|
||||
final Editor editor = CommonDataKeys.EDITOR.getData(context);
|
||||
resourceBundleEditor = editor != null ? editor.getUserData(ResourceBundleEditor.RESOURCE_BUNDLE_EDITOR_KEY) : null;
|
||||
}
|
||||
final ResourceBundleEditor resourceBundleEditor = (ResourceBundleEditor)editor;
|
||||
|
||||
final String prefix;
|
||||
final String separator;
|
||||
|
||||
+4
-1
@@ -47,6 +47,7 @@ import com.intellij.openapi.fileEditor.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.UserDataHolderBase;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
@@ -85,6 +86,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
|
||||
Logger.getInstance("#com.intellij.lang.properties.editor.ResourceBundleEditor");
|
||||
@NonNls private static final String VALUES = "values";
|
||||
@NonNls private static final String NO_PROPERTY_SELECTED = "noPropertySelected";
|
||||
public static final Key<ResourceBundleEditor> RESOURCE_BUNDLE_EDITOR_KEY = Key.create("resourceBundleEditor");
|
||||
|
||||
private final StructureViewComponent myStructureViewComponent;
|
||||
private final Map<PropertiesFile, Editor> myEditors;
|
||||
@@ -798,11 +800,12 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
|
||||
}
|
||||
}
|
||||
|
||||
private static Editor createEditor() {
|
||||
private Editor createEditor() {
|
||||
EditorFactory editorFactory = EditorFactory.getInstance();
|
||||
Document document = editorFactory.createDocument("");
|
||||
EditorEx editor = (EditorEx)editorFactory.createEditor(document);
|
||||
reinitSettings(editor);
|
||||
editor.putUserData(RESOURCE_BUNDLE_EDITOR_KEY, this);
|
||||
return editor;
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -28,6 +28,9 @@ public class StudyDocumentListener extends DocumentAdapter {
|
||||
// with fragments containing "\n"
|
||||
@Override
|
||||
public void beforeDocumentChange(DocumentEvent e) {
|
||||
if (!myTaskFile.isTrackChanges()) {
|
||||
return;
|
||||
}
|
||||
Document document = e.getDocument();
|
||||
myTaskWindows.clear();
|
||||
for (TaskWindow taskWindow : myTaskFile.getTaskWindows()) {
|
||||
@@ -39,6 +42,9 @@ public class StudyDocumentListener extends DocumentAdapter {
|
||||
|
||||
@Override
|
||||
public void documentChanged(DocumentEvent e) {
|
||||
if (!myTaskFile.isTrackChanges()) {
|
||||
return;
|
||||
}
|
||||
if (e instanceof DocumentEventImpl) {
|
||||
DocumentEventImpl event = (DocumentEventImpl)e;
|
||||
Document document = e.getDocument();
|
||||
|
||||
+2
-1
@@ -6,6 +6,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.jetbrains.edu.learning.course.Task;
|
||||
import com.jetbrains.edu.learning.course.TaskFile;
|
||||
import com.jetbrains.edu.learning.editor.StudyEditor;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class StudyState {
|
||||
private final StudyEditor myStudyEditor;
|
||||
@@ -15,7 +16,7 @@ public class StudyState {
|
||||
private final Task myTask;
|
||||
private final VirtualFile myTaskDir;
|
||||
|
||||
public StudyState(final StudyEditor studyEditor) {
|
||||
public StudyState(@Nullable final StudyEditor studyEditor) {
|
||||
myStudyEditor = studyEditor;
|
||||
myEditor = studyEditor != null ? studyEditor.getEditor() : null;
|
||||
myTaskFile = studyEditor != null ? studyEditor.getTaskFile() : null;
|
||||
|
||||
@@ -272,4 +272,10 @@ public class StudyUtils {
|
||||
extensions[0].setCommandLineParameters(cmd, project, filePath, pythonPath, currentTask);
|
||||
}
|
||||
}
|
||||
|
||||
public static void enableAction(@NotNull final AnActionEvent event, boolean isEnable) {
|
||||
final Presentation presentation = event.getPresentation();
|
||||
presentation.setVisible(isEnable);
|
||||
presentation.setEnabled(isEnable);
|
||||
}
|
||||
}
|
||||
|
||||
+67
-42
@@ -4,6 +4,7 @@ import com.intellij.ide.projectView.ProjectView;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
@@ -18,8 +19,7 @@ import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.jetbrains.edu.learning.StudyDocumentListener;
|
||||
import com.jetbrains.edu.learning.StudyTaskManager;
|
||||
import com.jetbrains.edu.learning.StudyState;
|
||||
import com.jetbrains.edu.learning.StudyUtils;
|
||||
import com.jetbrains.edu.learning.course.*;
|
||||
import com.jetbrains.edu.learning.editor.StudyEditor;
|
||||
@@ -30,8 +30,9 @@ import java.io.File;
|
||||
public class StudyRefreshTaskFileAction extends DumbAwareAction {
|
||||
public static final String ACTION_ID = "RefreshTaskAction";
|
||||
public static final String SHORTCUT = "ctrl shift pressed X";
|
||||
private static final Logger LOG = Logger.getInstance(StudyRefreshTaskFileAction.class.getName());
|
||||
|
||||
public static void refresh(final Project project) {
|
||||
public static void refresh(@NotNull final Project project) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -39,51 +40,54 @@ public class StudyRefreshTaskFileAction extends DumbAwareAction {
|
||||
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
|
||||
@Override
|
||||
public void run() {
|
||||
final Editor editor = StudyEditor.getSelectedEditor(project);
|
||||
assert editor != null;
|
||||
final Document document = editor.getDocument();
|
||||
refreshFile(editor, document, project);
|
||||
StudyEditor studyEditor = StudyEditor.getSelectedStudyEditor(project);
|
||||
StudyState studyState = new StudyState(studyEditor);
|
||||
if (studyEditor == null || !studyState.isValid()) {
|
||||
LOG.info("RefreshTaskFileAction was invoked outside of Study Editor");
|
||||
return;
|
||||
}
|
||||
refreshFile(studyState, project);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void refreshFile(@NotNull final Editor editor, @NotNull final Document document, @NotNull final Project project) {
|
||||
StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
|
||||
Course course = taskManager.getCourse();
|
||||
assert course != null;
|
||||
FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
|
||||
VirtualFile openedFile = fileDocumentManager.getFile(document);
|
||||
assert openedFile != null;
|
||||
final TaskFile selectedTaskFile = taskManager.getTaskFile(openedFile);
|
||||
assert selectedTaskFile != null;
|
||||
String openedFileName = openedFile.getName();
|
||||
Task currentTask = selectedTaskFile.getTask();
|
||||
resetTaskFile(document, project, course, selectedTaskFile, openedFileName, currentTask);
|
||||
selectedTaskFile.drawAllWindows(editor);
|
||||
selectedTaskFile.createGuardedBlocks(document, editor);
|
||||
private static void refreshFile(@NotNull final StudyState studyState, @NotNull final Project project) {
|
||||
final Editor editor = studyState.getEditor();
|
||||
final TaskFile taskFile = studyState.getTaskFile();
|
||||
if (!resetTaskFile(editor.getDocument(), project, taskFile, studyState.getVirtualFile().getName())) {
|
||||
return;
|
||||
}
|
||||
taskFile.drawAllWindows(editor);
|
||||
taskFile.createGuardedBlocks(editor);
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
IdeFocusManager.getInstance(project).requestFocus(editor.getContentComponent(), true);
|
||||
}
|
||||
});
|
||||
selectedTaskFile.navigateToFirstTaskWindow(editor);
|
||||
showBalloon(project);
|
||||
taskFile.navigateToFirstTaskWindow(editor);
|
||||
showBalloon(project, "You can start again now", MessageType.INFO);
|
||||
}
|
||||
|
||||
public static void resetTaskFile(Document document, Project project, Course course, TaskFile taskFile, String name, Task task) {
|
||||
resetDocument(document, course, name, task);
|
||||
updateLessonInfo(task);
|
||||
private static boolean resetTaskFile(@NotNull final Document document,
|
||||
@NotNull final Project project,
|
||||
TaskFile taskFile,
|
||||
String name) {
|
||||
if (!resetDocument(project, document, taskFile, name)) {
|
||||
return false;
|
||||
}
|
||||
updateLessonInfo(taskFile.getTask());
|
||||
StudyUtils.updateStudyToolWindow(project);
|
||||
resetTaskWindows(taskFile);
|
||||
ProjectView.getInstance(project).refresh();
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void showBalloon(Project project) {
|
||||
private static void showBalloon(@NotNull final Project project, String text, @NotNull final MessageType messageType) {
|
||||
BalloonBuilder balloonBuilder =
|
||||
JBPopupFactory.getInstance().createHtmlTextBalloonBuilder("You can start again now", MessageType.INFO, null);
|
||||
JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(text, messageType, null);
|
||||
final Balloon balloon = balloonBuilder.createBalloon();
|
||||
StudyEditor selectedStudyEditor = StudyEditor.getSelectedStudyEditor(project);
|
||||
assert selectedStudyEditor != null;
|
||||
@@ -104,33 +108,38 @@ public class StudyRefreshTaskFileAction extends DumbAwareAction {
|
||||
lessonInfo.update(StudyStatus.Unchecked, +1);
|
||||
}
|
||||
|
||||
private static void resetDocument(final Document document, Course course, String fileName, Task task) {
|
||||
private static boolean resetDocument(@NotNull final Project project,
|
||||
@NotNull final Document document,
|
||||
@NotNull final TaskFile taskFile,
|
||||
String fileName) {
|
||||
StudyEditor.deleteGuardedBlocks(document);
|
||||
StudyDocumentListener listener = StudyEditor.getListener(document);
|
||||
if (listener != null) {
|
||||
document.removeDocumentListener(listener);
|
||||
}
|
||||
taskFile.setTrackChanges(false);
|
||||
clearDocument(document);
|
||||
Task task = taskFile.getTask();
|
||||
String lessonDir = Lesson.LESSON_DIR + String.valueOf(task.getLesson().getIndex() + 1);
|
||||
String taskDir = Task.TASK_DIR + String.valueOf(task.getIndex() + 1);
|
||||
Course course = task.getLesson().getCourse();
|
||||
File resourceFile = new File(course.getResourcePath());
|
||||
File resourceRoot = resourceFile.getParentFile();
|
||||
if (!resourceFile.exists() || resourceRoot == null) {
|
||||
showBalloon(project, "Course was deleted", MessageType.ERROR);
|
||||
return false;
|
||||
}
|
||||
String patternPath = FileUtil.join(resourceRoot.getPath(), lessonDir, taskDir, fileName);
|
||||
VirtualFile patternFile = VfsUtil.findFileByIoFile(new File(patternPath), true);
|
||||
if (patternFile == null) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
Document patternDocument = FileDocumentManager.getInstance().getDocument(patternFile);
|
||||
final Document patternDocument = FileDocumentManager.getInstance().getDocument(patternFile);
|
||||
if (patternDocument == null) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
document.setText(patternDocument.getCharsSequence());
|
||||
if (listener != null) {
|
||||
document.addDocumentListener(listener);
|
||||
}
|
||||
taskFile.setTrackChanges(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void clearDocument(final Document document) {
|
||||
private static void clearDocument(@NotNull final Document document) {
|
||||
final int lineCount = document.getLineCount();
|
||||
if (lineCount != 0) {
|
||||
CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
|
||||
@@ -142,7 +151,23 @@ public class StudyRefreshTaskFileAction extends DumbAwareAction {
|
||||
}
|
||||
}
|
||||
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
refresh(e.getProject());
|
||||
public void actionPerformed(@NotNull AnActionEvent event) {
|
||||
final Project project = event.getProject();
|
||||
if (project != null) {
|
||||
refresh(project);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent event) {
|
||||
final Project project = event.getProject();
|
||||
if (project != null) {
|
||||
StudyEditor studyEditor = StudyEditor.getSelectedStudyEditor(project);
|
||||
StudyState studyState = new StudyState(studyEditor);
|
||||
if (studyState.isValid()) {
|
||||
StudyUtils.enableAction(event, true);
|
||||
}
|
||||
}
|
||||
StudyUtils.enableAction(event, false);
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -108,4 +108,8 @@ public class Lesson implements Stateful {
|
||||
}
|
||||
return myCourse.getLessons().get(myIndex - 1);
|
||||
}
|
||||
|
||||
public Course getCourse() {
|
||||
return myCourse;
|
||||
}
|
||||
}
|
||||
|
||||
+15
-2
@@ -36,6 +36,7 @@ public class TaskFile implements Stateful {
|
||||
private TaskWindow mySelectedTaskWindow = null;
|
||||
public int myIndex = -1;
|
||||
private boolean myUserCreated = false;
|
||||
private boolean myTrackChanges = true;
|
||||
|
||||
/**
|
||||
* @return if all the windows in task file are marked as resolved
|
||||
@@ -107,7 +108,7 @@ public class TaskFile implements Stateful {
|
||||
final Document document = editor.getDocument();
|
||||
EditorActionManager.getInstance()
|
||||
.setReadonlyFragmentModificationHandler(document, new TaskWindowDeleteHandler(editor));
|
||||
createGuardedBlocks(document, editor);
|
||||
createGuardedBlocks(editor);
|
||||
editor.getColorsScheme().setColor(EditorColors.READONLY_FRAGMENT_BACKGROUND_COLOR, null);
|
||||
}
|
||||
|
||||
@@ -227,11 +228,15 @@ public class TaskFile implements Stateful {
|
||||
/**
|
||||
* Marks symbols adjacent to task windows as read-only fragments
|
||||
*/
|
||||
public void createGuardedBlocks(@NotNull final Document document, @NotNull final Editor editor) {
|
||||
public void createGuardedBlocks(@NotNull final Editor editor) {
|
||||
final Document document = editor.getDocument();
|
||||
if (document instanceof DocumentImpl) {
|
||||
DocumentImpl documentImpl = (DocumentImpl)document;
|
||||
List<RangeMarker> blocks = documentImpl.getGuardedBlocks();
|
||||
for (TaskWindow taskWindow : taskWindows) {
|
||||
if (!taskWindow.isValid(document)) {
|
||||
return;
|
||||
}
|
||||
int start = taskWindow.getRealStartOffset(document);
|
||||
int end = start + taskWindow.getLength();
|
||||
if (start != 0) {
|
||||
@@ -249,4 +254,12 @@ public class TaskFile implements Stateful {
|
||||
.addRangeHighlighter(start, end, HighlighterLayer.LAST + 1, null, HighlighterTargetArea.EXACT_RANGE);
|
||||
blocks.add(rh);
|
||||
}
|
||||
|
||||
public boolean isTrackChanges() {
|
||||
return myTrackChanges;
|
||||
}
|
||||
|
||||
public void setTrackChanges(boolean trackChanges) {
|
||||
myTrackChanges = trackChanges;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* Implementation of StudyEditor which has panel with special buttons and task text
|
||||
* also @see {@link com.jetbrains.python.edu.editor.StudyFileEditorProvider}
|
||||
* also @see {@link com.jetbrains.edu.learning.editor.StudyFileEditorProvider}
|
||||
*/
|
||||
public class StudyEditor implements TextEditor {
|
||||
private static final String TASK_TEXT_HEADER = "Task Text";
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
package com.jetbrains.env;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.testFramework.UsefulTestCase;
|
||||
import com.intellij.util.SystemProperties;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.jetbrains.python.fixtures.PyTestCase;
|
||||
import com.jetbrains.python.packaging.PyPackage;
|
||||
import com.jetbrains.python.packaging.PyPackageManager;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -57,6 +61,11 @@ public abstract class PyEnvTestCase extends UsefulTestCase {
|
||||
PyTestCase.initPlatformPrefix();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PyPackage getInstalledDjango(@NotNull final Sdk sdk) throws ExecutionException {
|
||||
return PyPackageManager.getInstance(sdk).findPackage("django", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.jetbrains.python;
|
||||
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.jetbrains.python.fixtures.PyLightProjectDescriptor;
|
||||
import com.jetbrains.python.fixtures.PyTestCase;
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jetbrains.python.fixtures;
|
||||
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleType;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.ContentEntry;
|
||||
import com.intellij.openapi.roots.ModifiableRootModel;
|
||||
import com.intellij.openapi.roots.OrderRootType;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.jetbrains.python.PythonMockSdk;
|
||||
import com.jetbrains.python.PythonModuleTypeBase;
|
||||
|
||||
/**
|
||||
* Project descriptor (extracted from {@link com.jetbrains.python.fixtures.PyTestCase}) and should be used with it.
|
||||
* @author Ilya.Kazakevich
|
||||
*/
|
||||
public class PyLightProjectDescriptor implements LightProjectDescriptor {
|
||||
private final String myPythonVersion;
|
||||
|
||||
public PyLightProjectDescriptor(String pythonVersion) {
|
||||
myPythonVersion = pythonVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleType getModuleType() {
|
||||
return PythonModuleTypeBase.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sdk getSdk() {
|
||||
return PythonMockSdk.findOrCreate(myPythonVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) {
|
||||
}
|
||||
|
||||
protected void createLibrary(ModifiableRootModel model, final String name, final String path) {
|
||||
final Library.ModifiableModel modifiableModel = model.getModuleLibraryTable().createLibrary(name).getModifiableModel();
|
||||
final VirtualFile home =
|
||||
LocalFileSystem.getInstance().refreshAndFindFileByPath(PathManager.getHomePath() + path);
|
||||
|
||||
modifiableModel.addRoot(home, OrderRootType.CLASSES);
|
||||
modifiableModel.commit();
|
||||
}
|
||||
}
|
||||
@@ -28,19 +28,12 @@ import com.intellij.find.findUsages.FindUsagesOptions;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleType;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.ContentEntry;
|
||||
import com.intellij.openapi.roots.ModifiableRootModel;
|
||||
import com.intellij.openapi.roots.OrderRootType;
|
||||
import com.intellij.openapi.roots.impl.FilePropertyPusher;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -62,8 +55,6 @@ import com.intellij.usages.Usage;
|
||||
import com.intellij.usages.rules.PsiElementUsage;
|
||||
import com.intellij.util.CommonProcessors.CollectProcessor;
|
||||
import com.jetbrains.python.PythonHelpersLocator;
|
||||
import com.jetbrains.python.PythonMockSdk;
|
||||
import com.jetbrains.python.PythonModuleTypeBase;
|
||||
import com.jetbrains.python.PythonTestUtil;
|
||||
import com.jetbrains.python.psi.LanguageLevel;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
@@ -318,37 +309,6 @@ public abstract class PyTestCase extends UsefulTestCase {
|
||||
configurator.configureProject(myFixture.getProject(), newPath, moduleRef);
|
||||
}
|
||||
|
||||
protected static class PyLightProjectDescriptor implements LightProjectDescriptor {
|
||||
private final String myPythonVersion;
|
||||
|
||||
public PyLightProjectDescriptor(String pythonVersion) {
|
||||
myPythonVersion = pythonVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleType getModuleType() {
|
||||
return PythonModuleTypeBase.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sdk getSdk() {
|
||||
return PythonMockSdk.findOrCreate(myPythonVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) {
|
||||
}
|
||||
|
||||
protected void createLibrary(ModifiableRootModel model, final String name, final String path) {
|
||||
final Library.ModifiableModel modifiableModel = model.getModuleLibraryTable().createLibrary(name).getModifiableModel();
|
||||
final VirtualFile home =
|
||||
LocalFileSystem.getInstance().refreshAndFindFileByPath(PathManager.getHomePath() + path);
|
||||
|
||||
modifiableModel.addRoot(home, OrderRootType.CLASSES);
|
||||
modifiableModel.commit();
|
||||
}
|
||||
}
|
||||
|
||||
public static void initPlatformPrefix() {
|
||||
PlatformTestCase.autodetectPlatformPrefix();
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user