Merge remote-tracking branch 'origin/master'

This commit is contained in:
Alexander Lobas
2012-06-15 13:22:35 +04:00
50 changed files with 949 additions and 49 deletions
@@ -33,6 +33,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.Key;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.xdebugger.AbstractDebuggerSession;
import com.intellij.xdebugger.breakpoints.ui.BreakpointItem;
import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroupingRule;
@@ -50,7 +51,6 @@ import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* @author nik
@@ -187,7 +187,7 @@ public class JavaDebuggerSupport extends DebuggerSupport {
}
private static class JavaBreakpointPanelProvider extends BreakpointPanelProvider<Breakpoint> {
private List<MyBreakpointManagerListener> myListeners = new CopyOnWriteArrayList<MyBreakpointManagerListener>();
private List<MyBreakpointManagerListener> myListeners = ContainerUtil.createEmptyCOWList();
@NotNull
public Collection<AbstractBreakpointPanel<Breakpoint>> getBreakpointPanels(@NotNull final Project project, @NotNull final DialogWrapper parentDialog) {
@@ -1278,6 +1278,7 @@ public class HighlightMethodUtil {
if (classReference != null) {
ConstructorParametersFixer.registerFixActions(classReference, constructorCall, info, getFixRange(infoElement));
ChangeMethodSignatureFromUsageFix.registerIntentions(results, list, info, null);
ChangeTypeArgumentsFix.registerIntentions(results, list, info, aClass);
ConvertDoubleToFloatFix.registerIntentions(results, list, info, null);
PermuteArgumentsFix.registerFix(info, constructorCall, toMethodCandidates(results), getFixRange(list));
ChangeParameterClassFix.registerQuickFixActions(constructorCall, list, info);
@@ -122,6 +122,7 @@ public class ChangeParameterClassFix extends ExtendsListFix {
if (rClass instanceof PsiAnonymousClass) return;
if (rClass.isInheritor(lClass, true)) return;
if (lClass.isInheritor(rClass, true)) return;
if (lClass == rClass) return;
QuickFixAction.registerQuickFixAction(info, new ChangeParameterClassFix(rClass, (PsiClassType)lType));
}
@@ -0,0 +1,165 @@
/*
* Copyright 2000-2012 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: cdr
* Date: Nov 13, 2002
* Time: 3:26:50 PM
* To change this template use Options | File Templates.
*/
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.CodeInsightUtilBase;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.intention.HighPriorityAction;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
public class ChangeTypeArgumentsFix implements IntentionAction, HighPriorityAction {
private final PsiMethod myTargetMethod;
private final PsiClass myPsiClass;
private final PsiExpression[] myExpressions;
private static final Logger LOG = Logger.getInstance("#" + ChangeTypeArgumentsFix.class.getName());
private final PsiNewExpression myNewExpression;
ChangeTypeArgumentsFix(@NotNull PsiMethod targetMethod,
PsiClass psiClass,
@NotNull PsiExpression[] expressions,
@NotNull PsiElement context) {
myTargetMethod = targetMethod;
myPsiClass = psiClass;
myExpressions = expressions;
myNewExpression = PsiTreeUtil.getParentOfType(context, PsiNewExpression.class);
}
@Override
@NotNull
public String getText() {
final PsiSubstitutor substitutor = inferTypeArguments();
return "Change type arguments to <" + StringUtil.join(myPsiClass.getTypeParameters(), new Function<PsiTypeParameter, String>() {
@Override
public String fun(PsiTypeParameter typeParameter) {
return substitutor.substitute(typeParameter).getPresentableText();
}
}, ", ") + ">";
}
@Override
@NotNull
public String getFamilyName() {
return "Change type arguments";
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
final PsiTypeParameter[] typeParameters = myPsiClass.getTypeParameters();
if (typeParameters.length > 0) {
if (myNewExpression != null && myNewExpression.isValid() && myNewExpression.getArgumentList() != null) {
final PsiJavaCodeReferenceElement reference = myNewExpression.getClassOrAnonymousClassReference();
if (reference != null) {
final PsiReferenceParameterList parameterList = reference.getParameterList();
if (parameterList != null) {
final PsiSubstitutor substitutor = inferTypeArguments();
final PsiParameter[] parameters = myTargetMethod.getParameterList().getParameters();
if (parameters.length != myExpressions.length) return false;
for (int i = 0, length = parameters.length; i < length; i++) {
PsiParameter parameter = parameters[i];
final PsiType expectedType = substitutor.substitute(parameter.getType());
if (!myExpressions[i].isValid()) return false;
final PsiType actualType = myExpressions[i].getType();
if (expectedType == null || actualType == null || !TypeConversionUtil.isAssignable(expectedType, actualType)) return false;
}
return true;
}
}
}
}
return false;
}
@Override
public void invoke(@NotNull final Project project, Editor editor, final PsiFile file) {
if (!CodeInsightUtilBase.prepareFileForWrite(file)) return;
final PsiTypeParameter[] typeParameters = myPsiClass.getTypeParameters();
final PsiSubstitutor psiSubstitutor = inferTypeArguments();
final PsiJavaCodeReferenceElement reference = myNewExpression.getClassOrAnonymousClassReference();
LOG.assertTrue(reference != null, myNewExpression);
final PsiReferenceParameterList parameterList = reference.getParameterList();
LOG.assertTrue(parameterList != null, myNewExpression);
PsiTypeElement[] elements = parameterList.getTypeParameterElements();
for (int i = elements.length - 1; i >= 0; i--) {
PsiTypeElement typeElement = elements[i];
final PsiType typeArg = psiSubstitutor.substitute(typeParameters[i]);
typeElement.replace(JavaPsiFacade.getElementFactory(project).createTypeElement(typeArg));
}
}
private PsiSubstitutor inferTypeArguments() {
final JavaPsiFacade facade = JavaPsiFacade.getInstance(myNewExpression.getProject());
final PsiResolveHelper resolveHelper = facade.getResolveHelper();
final PsiParameter[] parameters = myTargetMethod.getParameterList().getParameters();
final PsiExpressionList argumentList = myNewExpression.getArgumentList();
LOG.assertTrue(argumentList != null);
final PsiExpression[] expressions = argumentList.getExpressions();
return resolveHelper.inferTypeArguments(myPsiClass.getTypeParameters(), parameters, expressions,
PsiSubstitutor.EMPTY,
myNewExpression.getParent(),
DefaultParameterTypeInferencePolicy.INSTANCE);
}
public static void registerIntentions(@NotNull JavaResolveResult[] candidates,
@NotNull PsiExpressionList list,
@NotNull HighlightInfo highlightInfo,
PsiClass psiClass) {
if (candidates.length == 0) return;
PsiExpression[] expressions = list.getExpressions();
for (JavaResolveResult candidate : candidates) {
registerIntention(expressions, highlightInfo, psiClass, candidate, list);
}
}
private static void registerIntention(@NotNull PsiExpression[] expressions,
@NotNull HighlightInfo highlightInfo,
PsiClass psiClass,
@NotNull JavaResolveResult candidate,
@NotNull PsiElement context) {
if (!candidate.isStaticsScopeCorrect()) return;
PsiMethod method = (PsiMethod)candidate.getElement();
PsiSubstitutor substitutor = candidate.getSubstitutor();
if (method != null && context.getManager().isInProject(method)) {
final ChangeTypeArgumentsFix fix = new ChangeTypeArgumentsFix(method, psiClass, expressions, context);
QuickFixAction.registerQuickFixAction(highlightInfo, null, fix);
}
}
@Override
public boolean startInWriteAction() {
return true;
}
}
@@ -0,0 +1,10 @@
// "Make 'Generic' extend 'Generic'" "false"
class Generic<E> {
Generic(E arg) { }
}
class Tester {
void method() {
Generic<Integer> aIntegerGeneric = new <caret>Generic<String>("");
}
}
@@ -0,0 +1,11 @@
// "Change type arguments to <String>" "true"
class Generic<E> {
Generic(E arg) {
}
}
class Tester {
void method() {
new Generic<String>("hi");
}
}
@@ -0,0 +1,11 @@
// "Change type arguments to <String, Integer>" "true"
class Generic<E, K> {
Generic(E arg, K arg1) {
}
}
class Tester {
void method() {
new Generic<String, Integer>("hi", 1);
}
}
@@ -0,0 +1,13 @@
import java.io.Serializable;
// "Change type arguments to <Serializable>" "true"
class Generic<E> {
Generic(E arg, E arg1) {
}
}
class Tester {
void method() {
new Generic<Serializable>("hi", 1);
}
}
@@ -0,0 +1,11 @@
// "Change type arguments to <String>" "true"
class Generic<E> {
Generic(E arg) {
}
}
class Tester {
void method() {
new Generic<Integer>(<caret>"hi");
}
}
@@ -0,0 +1,11 @@
// "Change type arguments to <String>" "false"
class Generic<E> {
Generic(E arg, int i) {
}
}
class Tester {
void method() {
new Generic<String>(<caret>"hi", "");
}
}
@@ -0,0 +1,13 @@
// "Change type arguments to <String>" "false"
import java.util.List;
class Generic<E> {
Generic(E arg, List<E> arg1) {
}
}
class Tester {
void method() {
new Generic<Integer>(<caret>"hi", "hi");
}
}
@@ -0,0 +1,11 @@
// "Change type arguments to <String>" "false"
class Generic<E> {
Generic(E arg) {
}
}
class Tester {
void method() {
new Generic<Integer>(<caret>"hi"
}
}
@@ -0,0 +1,11 @@
// "Change type arguments to <String>" "false"
class Generic<E> {
Generic(E arg, int i) {
}
}
class Tester {
void method() {
new Generic<Integer>(<caret>"hi");
}
}
@@ -0,0 +1,11 @@
// "Change type arguments to <String, Integer>" "true"
class Generic<E, K> {
Generic(E arg, K arg1) {
}
}
class Tester {
void method() {
new Generic<Integer, Integer>(<caret>"hi", 1);
}
}
@@ -0,0 +1,11 @@
// "Change type arguments to <Serializable>" "true"
class Generic<E> {
Generic(E arg, E arg1) {
}
}
class Tester {
void method() {
new Generic<Integer>(<caret>"hi", 1);
}
}
@@ -0,0 +1,26 @@
/*
* Copyright 2000-2012 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.codeInsight.daemon.quickFix;
public class ChangeTypeArgumentsFixTest extends LightQuickFix15TestCase {
public void test() throws Exception { doAllTests(); }
@Override
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/changeTypeArgs";
}
}
@@ -22,6 +22,7 @@ import com.intellij.psi.*;
import com.intellij.psi.search.searches.SuperMethodsSearch;
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.PairProcessor;
import com.intellij.util.ProcessingContext;
import com.intellij.util.Processor;
@@ -38,6 +39,7 @@ public class PsiMethodPattern extends PsiMemberPattern<PsiMethod,PsiMethodPatter
public PsiMethodPattern withParameterCount(@NonNls final int paramCount) {
return with(new PatternCondition<PsiMethod>("withParameterCount") {
@Override
public boolean accepts(@NotNull final PsiMethod method, final ProcessingContext context) {
return method.getParameterList().getParametersCount() == paramCount;
}
@@ -46,12 +48,14 @@ public class PsiMethodPattern extends PsiMemberPattern<PsiMethod,PsiMethodPatter
/**
* Selects the corrected method by argument types
* @param types the array of FQN of the parameter types or wildcards.
* @param inputTypes the array of FQN of the parameter types or wildcards.
* The special values are:<bl><li>"?" - means any type</li><li>".." - instructs pattern to accept the rest of the arguments</li></bl>
* @return
*/
public PsiMethodPattern withParameters(@NonNls final String... types) {
public PsiMethodPattern withParameters(@NonNls final String... inputTypes) {
final String[] types = inputTypes.length == 0 ? ArrayUtil.EMPTY_STRING_ARRAY : inputTypes;
return with(new PatternCondition<PsiMethod>("withParameters") {
@Override
public boolean accepts(@NotNull final PsiMethod psiMethod, final ProcessingContext context) {
final PsiParameterList parameterList = psiMethod.getParameterList();
int dotsIndex = -1;
@@ -91,7 +95,7 @@ public class PsiMethodPattern extends PsiMemberPattern<PsiMethod,PsiMethodPatter
});
}
public PsiMethodPattern definedInClass(final @NonNls String qname) {
public PsiMethodPattern definedInClass(@NonNls final String qname) {
return definedInClass(PsiJavaPatterns.psiClass().withQualifiedName(qname));
}
@@ -103,6 +107,7 @@ public class PsiMethodPattern extends PsiMemberPattern<PsiMethod,PsiMethodPatter
if (!processor.process(t.getContainingClass(), context)) return false;
final Ref<Boolean> result = Ref.create(Boolean.TRUE);
SuperMethodsSearch.search(t, null, true, false).forEach(new Processor<MethodSignatureBackedByPsiMethod>() {
@Override
public boolean process(final MethodSignatureBackedByPsiMethod signature) {
if (!processor.process(signature.getMethod().getContainingClass(), context)) {
result.set(Boolean.FALSE);
@@ -118,6 +123,7 @@ public class PsiMethodPattern extends PsiMemberPattern<PsiMethod,PsiMethodPatter
public PsiMethodPattern constructor(final boolean isConstructor) {
return with(new PatternCondition<PsiMethod>("constructor") {
@Override
public boolean accepts(@NotNull final PsiMethod method, final ProcessingContext context) {
return method.isConstructor() == isConstructor;
}
@@ -127,6 +133,7 @@ public class PsiMethodPattern extends PsiMemberPattern<PsiMethod,PsiMethodPatter
public PsiMethodPattern withThrowsList(final ElementPattern<?> pattern) {
return with(new PatternCondition<PsiMethod>("withThrowsList") {
@Override
public boolean accepts(@NotNull final PsiMethod method, final ProcessingContext context) {
return pattern.accepts(method.getThrowsList());
}
@@ -19,11 +19,12 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.search.SearchScope;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
@@ -49,7 +50,7 @@ public class FindModel extends UserDataHolderBase implements Cloneable {
void findModelChanged(FindModel findModel);
}
private final CopyOnWriteArrayList<FindModelObserver> myObservers = new CopyOnWriteArrayList<FindModelObserver>();
private final List<FindModelObserver> myObservers = ContainerUtil.createEmptyCOWList();
public void addObserver(FindModelObserver observer) {
myObservers.add(observer);
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.lookup.impl;
import com.google.common.collect.ImmutableMap;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.ui.ClickListener;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.GridBag;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
@@ -34,7 +35,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
* @author peter
*/
public class Advertiser {
private final List<String> myTexts = new CopyOnWriteArrayList<String>();
private final List<String> myTexts = ContainerUtil.createEmptyCOWList();
private volatile Dimension myCachedPrefSize;
private final JPanel myComponent = new JPanel(new GridBagLayout()) {
private JLabel mySample = createLabel();
@@ -87,6 +87,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
// separate method needed for tests
public final void initializeConfigurationTypes(@NotNull final ConfigurationType[] factories) {
Arrays.sort(factories, new Comparator<ConfigurationType>() {
@Override
public int compare(final ConfigurationType o1, final ConfigurationType o2) {
return o1.getDisplayName().compareTo(o2.getDisplayName());
}
@@ -109,15 +110,19 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
initializeConfigurationTypes(configurationTypes);
}
@Override
public void disposeComponent() {
}
@Override
public void initComponent() {
}
@Override
public void projectOpened() {
}
@Override
@NotNull
public RunnerAndConfigurationSettings createConfiguration(final String name, final ConfigurationFactory factory) {
return createConfiguration(doCreateConfiguration(name, factory, true), factory);
@@ -134,6 +139,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
}
}
@Override
@NotNull
public RunnerAndConfigurationSettings createConfiguration(final RunConfiguration runConfiguration,
final ConfigurationFactory factory) {
@@ -145,14 +151,17 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
return settings;
}
@Override
public void projectClosed() {
myTemplateConfigurationsMap.clear();
}
@Override
public RunManagerConfig getConfig() {
return myConfig;
}
@Override
@NotNull
public ConfigurationType[] getConfigurationFactories() {
return myTypes.clone();
@@ -177,6 +186,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
/**
* Template configuration is not included
*/
@Override
@NotNull
public RunConfiguration[] getConfigurations(@NotNull final ConfigurationType type) {
@@ -191,6 +201,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
return array.toArray(new RunConfiguration[array.size()]);
}
@Override
@NotNull
public RunConfiguration[] getAllConfigurations() {
RunConfiguration[] result = new RunConfiguration[myConfigurations.size()];
@@ -215,6 +226,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
/**
* Template configuration is not included
*/
@Override
@NotNull
public RunnerAndConfigurationSettings[] getConfigurationSettings(@NotNull final ConfigurationType type) {
@@ -240,6 +252,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
return template;
}
@Override
public void addConfiguration(RunnerAndConfigurationSettings settings,
boolean shared,
List<BeforeRunTask> tasks, boolean addEnabledTemplateTasksIfAbsent) {
@@ -336,6 +349,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
}
}
@Override
@Nullable
public RunnerAndConfigurationSettings getSelectedConfiguration() {
if (mySelectedConfigurationId == null && myLoadedSelectedConfigurationUniqueName != null) {
@@ -344,6 +358,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
return mySelectedConfigurationId == null ? null : myConfigurations.get(mySelectedConfigurationId);
}
@Override
public void setSelectedConfiguration(@Nullable RunnerAndConfigurationSettings settings) {
setSelectedConfigurationId(settings == null ? null : settings.getConfiguration().getUniqueID());
if (settings != null) {
@@ -420,6 +435,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
return true;
}
@Override
public void writeExternal(@NotNull final Element parentNode) throws WriteExternalException {
writeContext(parentNode);
for (final RunnerAndConfigurationSettings runnerAndConfigurationSettings : myTemplateConfigurationsMap.values()) {
@@ -529,10 +545,12 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
}
@Override
public void readExternal(final Element parentNode) throws InvalidDataException {
clear();
final Comparator<Element> comparator = new Comparator<Element>() {
@Override
public int compare(Element a, Element b) {
final boolean aDefault = Boolean.valueOf(a.getAttributeValue("default", "false"));
final boolean bDefault = Boolean.valueOf(b.getAttributeValue("default", "false"));
@@ -716,11 +734,13 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
return null;
}
@Override
@NotNull
public String getComponentName() {
return "RunManager";
}
@Override
public void setTemporaryConfiguration(@Nullable final RunnerAndConfigurationSettings tempConfiguration) {
if (tempConfiguration == null) return;
@@ -748,18 +768,22 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
return result.values();
}
@Override
public boolean isTemporary(@NotNull final RunConfiguration configuration) {
return Arrays.asList(getTempConfigurations()).contains(configuration);
}
@Override
public boolean isTemporary(@NotNull RunnerAndConfigurationSettings settings) {
return settings.isTemporary();
}
@Override
@NotNull
public RunConfiguration[] getTempConfigurations() {
List<RunConfiguration> configurations =
ContainerUtil.mapNotNull(myConfigurations.values(), new NullableFunction<RunnerAndConfigurationSettings, RunConfiguration>() {
@Override
public RunConfiguration fun(RunnerAndConfigurationSettings settings) {
return settings.isTemporary() ? settings.getConfiguration() : null;
}
@@ -767,6 +791,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
return configurations.toArray(new RunConfiguration[configurations.size()]);
}
@Override
public void makeStable(@NotNull RunConfiguration configuration) {
RunnerAndConfigurationSettings settings = getSettings(configuration);
if (settings != null) {
@@ -780,11 +805,13 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
}
}
@Override
@NotNull
public RunnerAndConfigurationSettings createRunConfiguration(String name, ConfigurationFactory type) {
return createConfiguration(name, type);
}
@Override
public boolean isConfigurationShared(final RunnerAndConfigurationSettings settings) {
Boolean shared = mySharedConfigurations.get(settings.getConfiguration().getUniqueID());
if (shared == null) {
@@ -794,6 +821,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
return shared != null && shared.booleanValue();
}
@Override
@NotNull
public <T extends BeforeRunTask> List<T> getBeforeRunTasks(Key<T> taskProviderID) {
final List<T> tasks = new ArrayList<T>();
@@ -822,10 +850,12 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
return tasks;
}
@Override
public void invalidateConfigurationIcon(@NotNull final RunnerAndConfigurationSettings settings) {
myIdToIcon.remove(settings.getConfiguration().getUniqueID());
}
@Override
public Icon getConfigurationIcon(@NotNull final RunnerAndConfigurationSettings settings) {
final int uniqueID = settings.getConfiguration().getUniqueID();
Icon icon = myIdToIcon.get(uniqueID);
@@ -881,6 +911,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
return result;
}
@Override
@NotNull
public List<BeforeRunTask> getBeforeRunTasks(final RunConfiguration settings) {
final List<BeforeRunTask> tasks = myConfigurationToBeforeTasksMap.get(settings);
@@ -920,7 +951,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
result.add(task.clone());
}
}
return result;
return result.isEmpty() ? Collections.<BeforeRunTask>emptyList() : result;
}
public void shareConfiguration(final RunConfiguration runConfiguration, final boolean shareConfiguration) {
@@ -933,6 +964,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
if (shouldFire) fireRunConfigurationChanged(settings);
}
@Override
public final void setBeforeRunTasks(final RunConfiguration runConfiguration, @NotNull List<BeforeRunTask> tasks, boolean addEnabledTemplateTasksIfAbsent) {
List<BeforeRunTask> result = new ArrayList<BeforeRunTask>(tasks);
if (addEnabledTemplateTasksIfAbsent) {
@@ -949,7 +981,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
}
}
}
myConfigurationToBeforeTasksMap.put(runConfiguration, result);
myConfigurationToBeforeTasksMap.put(runConfiguration, result.isEmpty() ? Collections.<BeforeRunTask>emptyList() : result);
fireBeforeRunTasksUpdated();
}
@@ -958,6 +990,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
fireBeforeRunTasksUpdated();
}
@Override
public void addConfiguration(final RunnerAndConfigurationSettings settings, final boolean isShared) {
addConfiguration(settings, isShared, getTemplateBeforeRunTasks(settings.getConfiguration()), false);
}
@@ -22,8 +22,8 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
@@ -53,7 +53,6 @@ public class ReloadFromDiskAction extends AnAction implements DumbAware {
new Runnable() {
public void run() {
PsiManager.getInstance(project).reloadFromDisk(psiFile);
CommandProcessor.getInstance().markCurrentCommandAsGlobal(project);
}
}
);
@@ -31,7 +31,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class ChangeSet {
private final long myId;
@@ -44,7 +43,7 @@ public class ChangeSet {
public ChangeSet(long id, long timestamp) {
myId = id;
myTimestamp = timestamp;
myChanges = new CopyOnWriteArrayList<Change>();
myChanges = ContainerUtil.createEmptyCOWList();
}
public ChangeSet(DataInput in) throws IOException {
@@ -38,6 +38,7 @@ import com.intellij.ui.tabs.impl.singleRow.SingleRowLayout;
import com.intellij.ui.tabs.impl.singleRow.SingleRowPassInfo;
import com.intellij.ui.tabs.impl.table.TableLayout;
import com.intellij.ui.tabs.impl.table.TablePassInfo;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.Animator;
import com.intellij.util.ui.JBInsets;
import com.intellij.util.ui.TimedDeadzone;
@@ -80,8 +81,8 @@ public class JBTabsImpl extends JComponent
private Insets myInnerInsets = JBInsets.NONE;
private final List<EventListener> myTabMouseListeners = new CopyOnWriteArrayList<EventListener>();
private final List<TabsListener> myTabListeners = new CopyOnWriteArrayList<TabsListener>();
private final List<EventListener> myTabMouseListeners = ContainerUtil.createEmptyCOWList();
private final List<TabsListener> myTabListeners = ContainerUtil.createEmptyCOWList();
private boolean myFocused;
private Getter<ActionGroup> myPopupGroup;
@@ -47,6 +47,7 @@ import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.content.Content;
import com.intellij.ui.content.ContentFactory;
import com.intellij.util.containers.CollectionFactory;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.hash.LinkedHashMap;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NonNls;
@@ -344,7 +345,7 @@ public class EventLog implements Notifications {
public static class ProjectTracker extends AbstractProjectComponent {
private volatile EventLogConsole myConsole;
private final List<Notification> myInitial = new CopyOnWriteArrayList<Notification>();
private final List<Notification> myInitial = ContainerUtil.createEmptyCOWList();
private final LogModel myProjectModel;
public ProjectTracker(@NotNull final Project project) {
@@ -180,7 +180,7 @@ public class CommandMerger {
myForcedGlobal = true;
}
private boolean isTransparent() {
public boolean isTransparent() {
return myTransparent;
}
@@ -16,8 +16,10 @@
package com.intellij.openapi.command.impl;
import com.intellij.CommonBundle;
import com.intellij.ide.DataManager;
import com.intellij.idea.ActionsBundle;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.*;
@@ -43,6 +45,7 @@ import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.util.containers.HashSet;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
@@ -253,7 +256,7 @@ public class UndoManagerImpl extends UndoManager implements ProjectComponent, Ap
myCommandLevel--;
if (myCommandLevel > 0) return;
if (myProject != null && myCurrentMerger.hasActions() && !myCurrentMerger.isGlobal()) {
if (myProject != null && !myCurrentMerger.isGlobal() && myCurrentMerger.hasActions() && !myCurrentMerger.isTransparent()) {
addFocusedDocumentAsAffected();
}
@@ -264,14 +267,14 @@ public class UndoManagerImpl extends UndoManager implements ProjectComponent, Ap
}
private void addFocusedDocumentAsAffected() {
VirtualFile[] selected = FileEditorManager.getInstance(myProject).getSelectedFiles();
if (selected.length == 0) return;
PsiFile psiFile = LangDataKeys.PSI_FILE.getData(DataManager.getInstance().getDataContext());
if (psiFile == null) return;
final DocumentReference[] refs = new DocumentReference[selected.length];
for (int i = 0; i < refs.length; i++) {
refs[i] = DocumentReferenceManager.getInstance().create(selected[i]);
}
VirtualFile file = psiFile.getVirtualFile();
if (file == null) return;
final DocumentReference[] refs = new DocumentReference[]{DocumentReferenceManager.getInstance().create(file)};
myCurrentMerger.addAction(new BasicUndoableAction() {
@Override
public void undo() throws UnexpectedUndoException {
@@ -85,8 +85,10 @@ public class DuplicateAction extends EditorAction {
final int lineToCheck = nextLineStart.line - 1;
int newOffset = end + offset - start;
if(lineToCheck == document.getLineCount () /*empty document*/ ||
document.getLineSeparatorLength(lineToCheck) == 0) {
if(lineToCheck == document.getLineCount () /* empty document */
|| nextLineStart.line == document.getLineCount() - 1 /* last line*/
|| document.getLineSeparatorLength(lineToCheck) == 0)
{
s = "\n"+s;
newOffset++;
}
@@ -21,6 +21,7 @@ import com.intellij.codeStyle.CodeStyleFacade;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.UndoConfirmationPolicy;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diff.DiffManager;
@@ -578,7 +579,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl
}
);
}
}, UIBundle.message("file.cache.conflict.action"), null);
}, UIBundle.message("file.cache.conflict.action"), null, UndoConfirmationPolicy.REQUEST_CONFIRMATION);
myUnsavedDocuments.remove(document);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 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.
@@ -28,7 +28,7 @@ public abstract class KeymapManagerEx extends KeymapManager {
}
/**
* @return all available keymaps. The method return an aempty array if no
* @return all available keymaps. The method return an empty array if no
* keymaps are available.
*/
public abstract Keymap[] getAllKeymaps();
@@ -16,12 +16,12 @@
package com.intellij.openapi.wm.impl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.util.containers.ContainerUtil;
import java.awt.*;
import java.awt.event.AWTEventListener;
import java.awt.event.KeyEvent;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* @author pegov
@@ -37,7 +37,7 @@ public class AltStateManager implements AWTEventListener {
}
}
private final List<AltListener> myListeners = new CopyOnWriteArrayList<AltListener>();
private final List<AltListener> myListeners = ContainerUtil.createEmptyCOWList();
public interface AltListener {
void altPressed();
@@ -26,6 +26,7 @@ import com.intellij.openapi.util.text.StringUtilRt;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.util.Alarm;
import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -440,7 +441,7 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen
private Color myColor;
private CopyOnWriteArrayList<ColorListener> myListeners = new CopyOnWriteArrayList<ColorListener>();
private CopyOnWriteArrayList<ColorListener> myListeners = ContainerUtil.createEmptyCOWList();
private int myOpacity;
private ColorWheel() {
@@ -19,12 +19,13 @@ import com.intellij.codeInsight.hint.HintUtil;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.List;
/**
* @author Alexey Pegov
@@ -37,9 +38,9 @@ class SlideComponent extends JComponent {
private final boolean myVertical;
private final String myTitle;
private CopyOnWriteArrayList<Consumer<Integer>> myListeners = new CopyOnWriteArrayList<Consumer<Integer>>();
private final List<Consumer<Integer>> myListeners = ContainerUtil.createEmptyCOWList();
private LightweightHint myTooltipHint;
private JLabel myLabel = new JLabel();
private final JLabel myLabel = new JLabel();
SlideComponent(String title, boolean vertical) {
myTitle = title;
@@ -17,10 +17,11 @@ package com.intellij.openapi.util.registry;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.util.Disposer;
import com.intellij.util.containers.ContainerUtil;
import java.awt.*;
import java.util.List;
import java.util.MissingResourceException;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* @author Kirill Kalishev
@@ -31,7 +32,7 @@ public class RegistryValue {
private final Registry myRegistry;
private final String myKey;
private final CopyOnWriteArraySet<RegistryValueListener> myListeners = new CopyOnWriteArraySet<RegistryValueListener>();
private final List<RegistryValueListener> myListeners = ContainerUtil.createEmptyCOWList();
private boolean myChangedSinceStart;
@@ -29,42 +29,52 @@ import java.lang.reflect.TypeVariable;
@SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})
public class ReflectionCache {
private static final ConcurrentFactoryMap<Class,Class> ourSuperClasses = new ConcurrentFactoryMap<Class, Class>() {
@Override
protected Class create(final Class key) {
return key.getSuperclass();
}
};
private static final ConcurrentFactoryMap<Class,Class[]> ourInterfaces = new ConcurrentFactoryMap<Class, Class[]>() {
@Override
@NotNull
protected Class[] create(final Class key) {
return key.getInterfaces();
Class[] classes = key.getInterfaces();
return classes.length == 0 ? ArrayUtil.EMPTY_CLASS_ARRAY : classes;
}
};
private static final Method[] EMPTY_METHODS = new Method[0];
private static final ConcurrentFactoryMap<Class, Method[]> ourMethods = new ConcurrentFactoryMap<Class, Method[]>() {
@Override
@NotNull
protected Method[] create(final Class key) {
return key.getMethods();
Method[] methods = key.getMethods();
return methods.length == 0 ? EMPTY_METHODS : methods;
}
};
private static final ConcurrentFactoryMap<Class,Boolean> ourIsInterfaces = new ConcurrentFactoryMap<Class, Boolean>() {
@Override
@NotNull
protected Boolean create(final Class key) {
return key.isInterface();
}
};
private static final ConcurrentFactoryMap<Class, TypeVariable[]> ourTypeParameters = new ConcurrentFactoryMap<Class, TypeVariable[]>() {
@Override
@NotNull
protected TypeVariable[] create(final Class key) {
return key.getTypeParameters();
}
};
private static final ConcurrentFactoryMap<Class, Type[]> ourGenericInterfaces = new ConcurrentFactoryMap<Class, Type[]>() {
@Override
@NotNull
protected Type[] create(final Class key) {
return key.getGenericInterfaces();
}
};
private static final ConcurrentFactoryMap<ParameterizedType, Type[]> ourActualTypeArguments = new ConcurrentFactoryMap<ParameterizedType, Type[]>() {
@Override
@NotNull
protected Type[] create(final ParameterizedType key) {
return key.getActualTypeArguments();
@@ -24,6 +24,7 @@ import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.xdebugger.XDebuggerManager;
import com.intellij.xdebugger.XDebuggerUtil;
import com.intellij.xdebugger.breakpoints.*;
@@ -40,14 +41,13 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* @author nik
*/
public class XBreakpointPanelProvider extends BreakpointPanelProvider<XBreakpoint> {
private List<MyXBreakpointListener> myListeners = new CopyOnWriteArrayList<MyXBreakpointListener>();
private final List<MyXBreakpointListener> myListeners = ContainerUtil.createEmptyCOWList();
@Override
public void createBreakpointsGroupingRules(Collection<XBreakpointGroupingRule> rules) {
@@ -173,7 +173,7 @@ public class XBreakpointPanelProvider extends BreakpointPanelProvider<XBreakpoin
private class AddXBreakpointAction extends AnAction {
private XBreakpointType<?, ?> myType;
private final XBreakpointType<?, ?> myType;
public AddXBreakpointAction(XBreakpointType<?, ?> type) {
myType = type;
@@ -19,6 +19,7 @@ import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizable;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.OrderedSet;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
@@ -48,7 +49,7 @@ public class ExternalizableStringSet extends OrderedSet<String>
* note: reference to defaultValues is retained by this set!
*/
public ExternalizableStringSet(@NonNls String... defaultValues) {
this.defaultValues = defaultValues;
this.defaultValues = defaultValues.length == 0 ? ArrayUtil.EMPTY_STRING_ARRAY : defaultValues;
for (String defaultValue : defaultValues) {
add(defaultValue);
}
@@ -17,6 +17,9 @@
package standardDsls
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.plugins.groovy.dgm.GroovyExtensionProvider
/**
* @author Maxim.Medvedev
*/
@@ -35,4 +38,12 @@ contributor([:]) {
category "org.codehaus.groovy.runtime.SwingGroovyMethods"
category "org.codehaus.groovy.runtime.XmlGroovyMethods"
def pair = GroovyExtensionProvider.getInstance(project).collectExtensions(GlobalSearchScope.allScope(project))
for (def inst : pair.first) {
category inst, false
}
for (def stat : pair.second) {
category stat, true
}
}
+12
View File
@@ -139,6 +139,10 @@
<groovyShellRunner implementation="org.jetbrains.plugins.groovy.console.DefaultGroovyShellRunner" order="last"/>
</extensions>
<extensions defaultExtensionNs="com.intellij.properties">
<implicitPropertyUsageProvider implementation="org.jetbrains.plugins.groovy.dgm.DGMImplicitPropertyUsageProvider"/>
</extensions>
<extensions defaultExtensionNs="com.intellij">
<testFramework implementation="org.jetbrains.plugins.groovy.testIntegration.GroovyTestFramework"/>
<testCreator language="Groovy" implementationClass="com.intellij.testIntegration.JavaTestCreator"/>
@@ -163,6 +167,7 @@
<errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
<fileTypeFactory implementation="org.jetbrains.plugins.groovy.GroovyFileTypeLoader"/>
<fileTypeFactory implementation="org.jetbrains.plugins.groovy.dgm.DGMFileTypeFactory"/>
<projectConfigurable instance="org.jetbrains.plugins.groovy.gant.GantConfigurable"/>
@@ -290,6 +295,8 @@
<completion.contributor language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.completion.GrMethodMergingContributor"
id="grMethodMerger" order="before methodMerger"/>
<completion.contributor language="Properties" implementationClass="org.jetbrains.plugins.groovy.dgm.DGMCompletionContributor"/>
<completion.confidence language="Groovy" implementationClass="com.intellij.codeInsight.completion.UnfocusedNameIdentifier"
id="groovyNameIdentifier"/>
<completion.confidence language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionConfidence"
@@ -299,6 +306,8 @@
<completion.confidence language="Groovy" implementationClass="com.intellij.codeInsight.completion.AlwaysFocusLookup" id="groovyTrue"
order="last"/>
<psi.referenceContributor language="Properties" implementation="org.jetbrains.plugins.groovy.dgm.DGMReferenceContributor"/>
<weigher key="completion" implementationClass="org.jetbrains.plugins.groovy.lang.completion.weighers.GrWithWeigher"
id="groovyWithWeigher" order="before stats"/>
<weigher key="completion" implementationClass="org.jetbrains.plugins.groovy.lang.completion.weighers.GrKindWeigher"
@@ -413,6 +422,9 @@
<projectService serviceInterface="org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager"
serviceImplementation="org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager"/>
<projectService serviceInterface="org.jetbrains.plugins.groovy.dgm.GroovyExtensionProvider"
serviceImplementation="org.jetbrains.plugins.groovy.dgm.GroovyExtensionProvider"/>
<problemFileHighlightFilter implementation="org.jetbrains.plugins.groovy.GroovyProblemFileHighlightFilter"/>
<renameInputValidator implementation="org.jetbrains.plugins.groovy.GroovyRenameInputValidator"/>
@@ -0,0 +1,95 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.dgm;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
/**
* @author Max Medvedev
*/
public class DGMClassReference implements PsiReference {
private final PsiElement myElement;
private TextRange myRange;
public DGMClassReference(PsiElement element, int start, int end) {
myElement = element;
myRange = new TextRange(start, end);
}
@Override
public PsiElement getElement() {
return myElement;
}
@Override
public TextRange getRangeInElement() {
return myRange;
}
@Override
public PsiElement resolve() {
Project project = myElement.getProject();
return JavaPsiFacade.getInstance(project).findClass(myRange.substring(myElement.getText()), myElement.getResolveScope());
}
@NotNull
@Override
public String getCanonicalText() {
return myRange.substring(myElement.getText());
}
@Override
public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
if (element instanceof PsiClass) {
String qname = ((PsiClass)element).getQualifiedName();
if (qname == null) return myElement;
PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myElement.getProject());
Document document = documentManager.getDocument(myElement.getContainingFile());
TextRange range = myRange.shiftRight(myElement.getTextRange().getStartOffset());
document.replaceString(range.getStartOffset(), range.getEndOffset(), qname);
documentManager.commitDocument(document);
}
return myElement;
}
@Override
public boolean isReferenceTo(PsiElement element) {
return myElement.getManager().areElementsEquivalent(element, resolve());
}
@NotNull
@Override
public Object[] getVariants() {
return EMPTY_ARRAY;
}
@Override
public boolean isSoft() {
return true;
}
}
@@ -0,0 +1,73 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.dgm;
import com.intellij.codeInsight.completion.*;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.lang.properties.parsing.PropertiesTokenTypes;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.util.Consumer;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionUtil;
import java.util.Map;
/**
* @author Max Medvedev
*/
public class DGMCompletionContributor extends CompletionContributor {
public DGMCompletionContributor() {
extend(CompletionType.BASIC, PlatformPatterns.psiElement(PropertiesTokenTypes.KEY_CHARACTERS),
new CompletionProvider<CompletionParameters>() {
@Override
protected void addCompletions(@NotNull CompletionParameters parameters,
ProcessingContext context,
@NotNull CompletionResultSet result) {
PsiElement position = parameters.getPosition();
if (!DGMUtil.isInDGMFile(position)) return;
Map<String, String> map = ((PropertiesFile)position.getContainingFile()).getNamesMap();
for (String key : DGMUtil.KEYS) {
if (!map.containsKey(key)) {
result.addElement(LookupElementBuilder.create(key));
}
}
}
});
extend(CompletionType.BASIC, PlatformPatterns.psiElement(PropertiesTokenTypes.VALUE_CHARACTERS),
new CompletionProvider<CompletionParameters>() {
@Override
protected void addCompletions(@NotNull CompletionParameters parameters,
ProcessingContext context,
@NotNull final CompletionResultSet result) {
PsiElement position = parameters.getPosition();
if (!DGMUtil.isInDGMFile(position)) return;
AllClassesGetter.processJavaClasses(parameters, result.getPrefixMatcher(), true, new Consumer<PsiClass>() {
@Override
public void consume(PsiClass aClass) {
result.addElement(GroovyCompletionUtil.createClassLookupItem(aClass));
}
});
}
});
}
}
@@ -0,0 +1,36 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.dgm;
import com.intellij.lang.properties.PropertiesFileType;
import com.intellij.openapi.fileTypes.ExactFileNameMatcher;
import com.intellij.openapi.fileTypes.FileTypeConsumer;
import com.intellij.openapi.fileTypes.FileTypeFactory;
import com.intellij.openapi.util.SystemInfo;
import org.jetbrains.annotations.NotNull;
/**
* @author Max Medvedev
*/
public class DGMFileTypeFactory extends FileTypeFactory {
@Override
public void createFileTypes(@NotNull FileTypeConsumer consumer) {
ExactFileNameMatcher matcher = new ExactFileNameMatcher(GroovyExtensionProvider.ORG_CODEHAUS_GROOVY_RUNTIME_EXTENSION_MODULE,
!SystemInfo.isFileSystemCaseSensitive);
consumer.consume(PropertiesFileType.INSTANCE, matcher);
}
}
@@ -0,0 +1,34 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.dgm;
import com.intellij.codeInspection.unused.ImplicitPropertyUsageProvider;
import com.intellij.lang.properties.psi.Property;
import com.intellij.util.ArrayUtil;
/**
* @author Max Medvedev
*/
public class DGMImplicitPropertyUsageProvider extends ImplicitPropertyUsageProvider {
@Override
protected boolean isUsed(Property property) {
if (DGMUtil.isInDGMFile(property)) {
String name = property.getName();
return ArrayUtil.find(DGMUtil.KEYS, name) >= 0;
}
return false;
}
}
@@ -0,0 +1,80 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.dgm;
import com.intellij.lang.properties.IProperty;
import com.intellij.lang.properties.parsing.PropertiesTokenTypes;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.*;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
/**
* @author Max Medvedev
*/
public class DGMReferenceContributor extends PsiReferenceContributor {
@Override
public void registerReferenceProviders(PsiReferenceRegistrar registrar) {
registrar.registerReferenceProvider(PlatformPatterns.psiElement(PropertiesTokenTypes.VALUE_CHARACTERS), new PsiReferenceProvider() {
@NotNull
@Override
public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
if (!DGMUtil.isInDGMFile(element)) return PsiReference.EMPTY_ARRAY;
IProperty parent = (IProperty)element.getParent();
if (!"extensionClasses".equals(parent.getName())) {
return PsiReference.EMPTY_ARRAY;
}
ArrayList<PsiReference> result = new ArrayList<PsiReference>();
String text = element.getText();
int i = 0;
while ((i = skipWhiteSpace(i, text)) < text.length()) {
int end = findWhiteSpaceOrComma(i, text);
if (end <= text.length()) {
result.add(new DGMClassReference(element, i, end));
}
i = end;
i = skipWhiteSpace(i, text);
if (i == text.length()) break;
if (text.charAt(i) == ',') i++;
i = skipWhiteSpace(i, text);
}
return result.toArray(new PsiReference[result.size()]);
}
});
}
private static int skipWhiteSpace(int i, String text) {
while (i < text.length() && Character.isWhitespace(text.charAt(i))) {
i++;
}
return i;
}
private static int findWhiteSpaceOrComma(int i, String text) {
while (i < text.length() && !Character.isWhitespace(text.charAt(i)) && text.charAt(i) != ',') {
i++;
}
return i;
}
}
@@ -0,0 +1,36 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.dgm;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
/**
* @author Max Medvedev
*/
public class DGMUtil {
public static final String[] KEYS = new String[]{"moduleName", "moduleVersion", "extensionClasses", "staticExtensionClasses",};
public static boolean isInDGMFile(PsiElement e) {
PsiFile file = e.getContainingFile();
return file instanceof PropertiesFile &&
Comparing.equal(file.getName(), GroovyExtensionProvider.ORG_CODEHAUS_GROOVY_RUNTIME_EXTENSION_MODULE,
SystemInfo.isFileSystemCaseSensitive);
}
}
@@ -0,0 +1,80 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.dgm;
import com.intellij.lang.properties.IProperty;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiPackage;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @author Max Medvedev
*/
public class GroovyExtensionProvider {
@NonNls public static final String ORG_CODEHAUS_GROOVY_RUNTIME_EXTENSION_MODULE = "org.codehaus.groovy.runtime.ExtensionModule";
private final Project myProject;
public GroovyExtensionProvider(Project project) {
myProject = project;
}
public static GroovyExtensionProvider getInstance(Project project) {
return ServiceManager.getService(project, GroovyExtensionProvider.class);
}
public Pair<List<String>, List<String>> collectExtensions(GlobalSearchScope resolveScope) {
PsiPackage aPackage = JavaPsiFacade.getInstance(myProject).findPackage("META-INF.services");
if (aPackage == null) {
return new Pair<List<String>, List<String>>(Collections.<String>emptyList(), Collections.<String>emptyList());
}
List<String> instanceClasses = new ArrayList<String>();
List<String> staticClasses = new ArrayList<String>();
for (PsiDirectory directory : aPackage.getDirectories(resolveScope)) {
PsiFile file = directory.findFile("org.codehaus.groovy.runtime.ExtensionModule");
if (file instanceof PropertiesFile) {
IProperty inst = ((PropertiesFile)file).findPropertyByKey("extensionClasses");
IProperty stat = ((PropertiesFile)file).findPropertyByKey("staticExtensionClasses");
if (inst != null) collectClasses(inst, instanceClasses);
if (stat != null) collectClasses(stat, staticClasses);
}
}
return new Pair<List<String>, List<String>>(instanceClasses, staticClasses);
}
private static void collectClasses(IProperty pr, List<String> classes) {
String value = pr.getValue();
if (value == null) return;
value = value.trim();
String[] qnames = value.split("\\s*,\\s*");
ContainerUtil.addAll(classes, qnames);
}
}
@@ -1053,4 +1053,21 @@ class Category2 {
assertNotNull(ref.resolve())
}
void testGroovyExtensions() {
def ref = configureByText('pack._a.groovy', '''\
package pack
class StringExt {
static sub(String s) {}
}
"".su<caret>b()''')
myFixture.addFileToProject("META-INF/services/org.codehaus.groovy.runtime.ExtensionModule", """\
extensionClasses=pack.StringExt
""")
assertNotNull(ref.resolve())
}
}
+6 -1
View File
@@ -6,6 +6,11 @@
This plugin enables smart editing of properties files.
</description>
<vendor logo="/general/ijLogo.png">JetBrains</vendor>
<extensionPoints>
<extensionPoint name="implicitPropertyUsageProvider" interface="com.intellij.codeInspection.unused.ImplicitPropertyUsageProvider"/>
</extensionPoints>
<extensions defaultExtensionNs="com.intellij">
<errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
<applicationService serviceInterface="com.intellij.lang.properties.LastSelectedPropertiesFileStore"
@@ -51,7 +56,7 @@
<localInspection language="Properties" shortName="UnusedProperty" bundle="messages.PropertiesBundle" key="unused.property.inspection.display.name"
groupKey="properties.files.inspection.group.display.name" enabledByDefault="true" level="WARNING"
implementationClass="com.intellij.lang.properties.UnusedPropertyInspection"/>
implementationClass="com.intellij.codeInspection.unused.UnusedPropertyInspection"/>
<globalInspection shortName="DuplicatePropertyInspection" bundle="messages.InspectionsBundle" key="duplicate.property.display.name"
groupKey="group.names.properties.files" enabledByDefault="false" level="WARNING"
implementationClass="com.intellij.codeInspection.duplicatePropertyInspection.DuplicatePropertyInspection"/>
@@ -0,0 +1,36 @@
/*
* Copyright 2000-2012 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.codeInspection.unused;
import com.intellij.lang.properties.psi.Property;
import com.intellij.openapi.extensions.ExtensionPointName;
/**
* @author Max Medvedev
*/
public abstract class ImplicitPropertyUsageProvider {
private static final ExtensionPointName<ImplicitPropertyUsageProvider> EP_NAME =
ExtensionPointName.create("com.intellij.properties.implicitPropertyUsageProvider");
public static boolean isImplicitlyUsed(Property property) {
for (ImplicitPropertyUsageProvider provider : EP_NAME.getExtensions()) {
if (provider.isUsed(property)) return true;
}
return false;
}
protected abstract boolean isUsed(Property property);
}
@@ -13,12 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.lang.properties;
package com.intellij.codeInspection.unused;
import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.lang.ASTNode;
import com.intellij.lang.properties.PropertiesBundle;
import com.intellij.lang.properties.PropertySuppressableInspectionBase;
import com.intellij.lang.properties.RemovePropertyLocalFix;
import com.intellij.lang.properties.findUsages.PropertySearcher;
import com.intellij.lang.properties.psi.Property;
import com.intellij.openapi.extensions.Extensions;
@@ -75,6 +78,8 @@ public class UnusedPropertyInspection extends PropertySuppressableInspectionBase
original.setText(PropertiesBundle.message("searching.for.property.key.progress.text", property.getUnescapedKey()));
}
if (ImplicitPropertyUsageProvider.isImplicitlyUsed(property)) return;
String name = property.getName();
if (name == null) return;
if (searcher != null) {
@@ -97,7 +102,7 @@ public class UnusedPropertyInspection extends PropertySuppressableInspectionBase
PsiElement key = nodes.length == 0 ? property : nodes[0].getPsi();
String description = PropertiesBundle.message("unused.property.problem.descriptor.name");
holder.registerProblem(key, description, ProblemHighlightType.LIKE_UNUSED_SYMBOL,RemovePropertyLocalFix.INSTANCE);
holder.registerProblem(key, description, ProblemHighlightType.LIKE_UNUSED_SYMBOL, RemovePropertyLocalFix.INSTANCE);
}
};
}
@@ -33,6 +33,7 @@ import com.intellij.spellchecker.dictionary.EditableDictionary;
import com.intellij.spellchecker.dictionary.EditableDictionaryLoader;
import com.intellij.spellchecker.dictionary.Loader;
import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
@@ -49,11 +50,11 @@ public class BaseSpellChecker implements SpellCheckerEngine {
private final Transformation transform = new Transformation();
private final Set<EditableDictionary> dictionaries = new THashSet<EditableDictionary>();
private final List<Dictionary> bundledDictionaries = new CopyOnWriteArrayList<Dictionary>();
private final List<Dictionary> bundledDictionaries = ContainerUtil.createEmptyCOWList();
private final Metrics metrics = new LevenshteinDistance();
private AtomicBoolean myLoadingDictionaries = new AtomicBoolean(false);
private List<Pair<Loader, Consumer<Dictionary>>> myDictionariesToLoad = new CopyOnWriteArrayList<Pair<Loader, Consumer<Dictionary>>>();
private List<Pair<Loader, Consumer<Dictionary>>> myDictionariesToLoad = ContainerUtil.createEmptyCOWList();
private Project myProject;
public BaseSpellChecker(final Project project) {