Merge branch origin/master

This commit is contained in:
Elizaveta Shashkova
2015-01-15 18:44:15 +03:00
106 changed files with 2267 additions and 1129 deletions
@@ -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
@@ -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);
@@ -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) {
@@ -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
@@ -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) {
@@ -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);
@@ -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 {
@@ -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();
}
}
@@ -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];
}
}
@@ -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];
}
}
@@ -0,0 +1,8 @@
class Test {
void foo(String s) {
bar(s.length());
bar(s.length() + 1);
}
void bar(int <caret>i){}
}
@@ -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);
}
}
@@ -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();
}
@@ -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);
@@ -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"));
@@ -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));
}
}
@@ -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;
@@ -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
@@ -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 {
@@ -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) {
@@ -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);
}
@@ -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));
}
}
@@ -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();
@@ -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;
}
}
}
@@ -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;
}
}
}
@@ -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(); }
}
+2 -21
View File
@@ -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;
}
}
+16 -55
View File
@@ -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);
}
@@ -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;
}
@@ -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());
}
@@ -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
@@ -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;
}
@@ -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) {
@@ -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;
}
@@ -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;
@@ -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;
}
@@ -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();
@@ -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);
}
}
@@ -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);
}
}
@@ -108,4 +108,8 @@ public class Lesson implements Stateful {
}
return myCourse.getLessons().get(myIndex - 1);
}
public Course getCourse() {
return myCourse;
}
}
@@ -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;
}
}
@@ -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";
+9
View File
@@ -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