mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git@git.labs.intellij.net:idea/community
This commit is contained in:
@@ -70,10 +70,12 @@ public class ExpectedTypesProvider {
|
||||
};
|
||||
private static final PsiType[] PRIMITIVE_TYPES = {PsiType.BYTE, PsiType.CHAR, PsiType.SHORT, PsiType.INT, PsiType.LONG, PsiType.FLOAT, PsiType.DOUBLE};
|
||||
|
||||
@NotNull
|
||||
public static ExpectedTypeInfo createInfo(@NotNull PsiType type, int kind, PsiType defaultType, TailType tailType) {
|
||||
return createInfoImpl(type, kind, defaultType, tailType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static ExpectedTypeInfoImpl createInfoImpl(@NotNull PsiType type, int kind, PsiType defaultType, TailType tailType) {
|
||||
int dims = 0;
|
||||
while (type instanceof PsiArrayType) {
|
||||
@@ -85,23 +87,27 @@ public class ExpectedTypesProvider {
|
||||
return new ExpectedTypeInfoImpl(type, kind, dims, defaultType, tailType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ExpectedTypeInfo[] getExpectedTypes(@Nullable PsiExpression expr, boolean forCompletion) {
|
||||
return getExpectedTypes(expr, forCompletion, false, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ExpectedTypeInfo[] getExpectedTypes(@Nullable PsiExpression expr, boolean forCompletion, final boolean voidable, boolean usedAfter) {
|
||||
return getExpectedTypes(expr, forCompletion, ourGlobalScopeClassProvider, voidable, usedAfter);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ExpectedTypeInfo[] getExpectedTypes(@Nullable PsiExpression expr,
|
||||
boolean forCompletion,
|
||||
ExpectedClassProvider classProvider, boolean usedAfter) {
|
||||
return getExpectedTypes(expr, forCompletion, classProvider, false, usedAfter);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ExpectedTypeInfo[] getExpectedTypes(@Nullable PsiExpression expr, boolean forCompletion, ExpectedClassProvider classProvider,
|
||||
final boolean voidable, boolean usedAfter) {
|
||||
if (expr == null) return null;
|
||||
if (expr == null) return ExpectedTypeInfo.EMPTY_ARRAY;
|
||||
PsiElement parent = expr.getParent();
|
||||
while (parent instanceof PsiParenthesizedExpression) {
|
||||
expr = (PsiExpression)parent;
|
||||
|
||||
@@ -103,6 +103,8 @@ public class OverrideImplementUtil {
|
||||
PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(aClass.getProject()).getResolveHelper();
|
||||
for (HierarchicalMethodSignature signature : allMethodSigs) {
|
||||
PsiMethod method = signature.getMethod();
|
||||
LOG.assertTrue(method.isValid());
|
||||
|
||||
if (method.hasModifierProperty(PsiModifier.STATIC) || !resolveHelper.isAccessible(method, aClass, aClass)) continue;
|
||||
PsiClass hisClass = method.getContainingClass();
|
||||
if (hisClass == null) continue;
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.navigation.ItemPresentation;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import com.intellij.openapi.util.UserDataHolderBase;
|
||||
@@ -84,9 +85,11 @@ public abstract class ElementBase extends UserDataHolderBase implements Iconable
|
||||
baseIcon = myBaseIcon.get(flags);
|
||||
}
|
||||
|
||||
final Project project = psiElement.getProject();
|
||||
if (isToDeferIconLoading()) {
|
||||
return IconDeferrer.getInstance().defer(baseIcon, new ElementIconRequest(psiElement, flags), new NullableFunction<ElementIconRequest, Icon>() {
|
||||
public Icon fun(ElementIconRequest request) {
|
||||
if (project.isDisposed()) return null;
|
||||
final PsiElement element = request.getElement();
|
||||
if (!element.isValid()) return null;
|
||||
if (element.getProject().isDisposed()) return null;
|
||||
|
||||
@@ -32,7 +32,7 @@ public class ProximityLocation implements UserDataHolder {
|
||||
private final Module myPositionModule;
|
||||
private final ProcessingContext myContext;
|
||||
|
||||
public ProximityLocation(final PsiElement position, final Module positionModule) {
|
||||
public ProximityLocation(@Nullable final PsiElement position, final Module positionModule) {
|
||||
this(position, positionModule, new ProcessingContext());
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -218,7 +218,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
@NotNull
|
||||
private LookupImpl obtainLookup(Editor editor, CompletionParameters parameters) {
|
||||
LookupImpl existing = (LookupImpl)LookupManager.getActiveLookup(editor);
|
||||
if (existing != null) {
|
||||
if (existing != null && existing.isCompletion()) {
|
||||
existing.markReused();
|
||||
if (!autopopup) {
|
||||
existing.setFocused(true);
|
||||
|
||||
@@ -698,6 +698,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
|
||||
int index = myList.getSelectedIndex();
|
||||
Rectangle itmBounds = myList.getCellBounds(index, index);
|
||||
if (itmBounds == null){
|
||||
LOG.error("No bounds for " + index + "; size=" + myList.getModel().getSize());
|
||||
return null;
|
||||
}
|
||||
Point layeredPanePoint=SwingUtilities.convertPoint(myList,itmBounds.x,itmBounds.y,getComponent());
|
||||
|
||||
@@ -1375,7 +1375,7 @@ public abstract class ChooseByNameBase {
|
||||
private final ChooseByNameModel myModel;
|
||||
private final PsiProximityComparator myProximityComparator;
|
||||
|
||||
private PathProximityComparator(final ChooseByNameModel model, final PsiElement context) {
|
||||
private PathProximityComparator(final ChooseByNameModel model, @Nullable final PsiElement context) {
|
||||
myModel = model;
|
||||
myProximityComparator = new PsiProximityComparator(context);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.intellij.openapi.roots.*;
|
||||
import com.intellij.openapi.startup.StartupManager;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.openapi.vfs.impl.BulkVirtualFileListenerAdapter;
|
||||
@@ -175,8 +176,9 @@ public class DirectoryIndexImpl extends DirectoryIndex implements ProjectCompone
|
||||
}
|
||||
|
||||
private void doInitialize() {
|
||||
myState = new IndexState();
|
||||
myState.doInitialize(false);
|
||||
IndexState newState = new IndexState();
|
||||
newState.doInitialize(false);
|
||||
myState = newState;
|
||||
}
|
||||
|
||||
private boolean isExcludeRootForModule(Module module, VirtualFile excludeRoot) {
|
||||
@@ -219,12 +221,13 @@ public class DirectoryIndexImpl extends DirectoryIndex implements ProjectCompone
|
||||
}
|
||||
};
|
||||
|
||||
private class PackageSink extends QueryFactory<VirtualFile, List<VirtualFile>> {
|
||||
private class PackageSink extends QueryFactory<VirtualFile, Pair<IndexState, List<VirtualFile>>> {
|
||||
private PackageSink() {
|
||||
registerExecutor(new QueryExecutor<VirtualFile, List<VirtualFile>>() {
|
||||
public boolean execute(@NotNull final List<VirtualFile> allDirs, @NotNull final Processor<VirtualFile> consumer) {
|
||||
for (VirtualFile dir : allDirs) {
|
||||
DirectoryInfo info = getInfoForDirectory(dir);
|
||||
registerExecutor(new QueryExecutor<VirtualFile, Pair<IndexState, List<VirtualFile>>>() {
|
||||
public boolean execute(@NotNull final Pair<IndexState, List<VirtualFile>> stateAndDirs,
|
||||
@NotNull final Processor<VirtualFile> consumer) {
|
||||
for (VirtualFile dir : stateAndDirs.second) {
|
||||
DirectoryInfo info = stateAndDirs.first.myDirToInfoMap.get(dir);
|
||||
assert info != null;
|
||||
|
||||
if (!info.isInLibrarySource || info.libraryClassRoot != null) {
|
||||
@@ -237,15 +240,21 @@ public class DirectoryIndexImpl extends DirectoryIndex implements ProjectCompone
|
||||
}
|
||||
|
||||
public Query<VirtualFile> search(@NotNull String packageName, boolean includeLibrarySources) {
|
||||
List<VirtualFile> allDirs = doGetDirectoriesByPackageName(packageName);
|
||||
return new FilteredQuery<VirtualFile>(includeLibrarySources ? new CollectionQuery<VirtualFile>(allDirs) : createQuery(allDirs),
|
||||
IS_VALID);
|
||||
checkAvailability();
|
||||
dispatchPendingEvents();
|
||||
|
||||
IndexState state = myState;
|
||||
List<VirtualFile> allDirs = state.myPackageNameToDirsMap.get(packageName);
|
||||
if (allDirs == null) allDirs = Collections.emptyList();
|
||||
|
||||
Query<VirtualFile> query = includeLibrarySources ? new CollectionQuery<VirtualFile>(allDirs)
|
||||
: createQuery(Pair.create(state, allDirs));
|
||||
return new FilteredQuery<VirtualFile>(query, IS_VALID);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Query<VirtualFile> getDirectoriesByPackageName(@NotNull String packageName, boolean includeLibrarySources) {
|
||||
checkAvailability();
|
||||
return mySink.search(packageName, includeLibrarySources);
|
||||
}
|
||||
|
||||
@@ -255,14 +264,6 @@ public class DirectoryIndexImpl extends DirectoryIndex implements ProjectCompone
|
||||
return myState.myDirToPackageName.get(dir);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<VirtualFile> doGetDirectoriesByPackageName(@NotNull String packageName) {
|
||||
dispatchPendingEvents();
|
||||
|
||||
List<VirtualFile> dirs = myState.myPackageNameToDirsMap.get(packageName);
|
||||
return dirs != null ? dirs : Collections.<VirtualFile>emptyList();
|
||||
}
|
||||
|
||||
private void dispatchPendingEvents() {
|
||||
myConnection.deliverImmediately();
|
||||
}
|
||||
@@ -370,9 +371,10 @@ public class DirectoryIndexImpl extends DirectoryIndex implements ProjectCompone
|
||||
|
||||
IndexState copy = null;
|
||||
for (VirtualFile dir : list) {
|
||||
DirectoryInfo info = myState.myDirToInfoMap.remove(dir);
|
||||
if (info != null) {
|
||||
if (myState.myDirToInfoMap.containsKey(dir)) {
|
||||
if (copy == null) copy = myState.copy();
|
||||
|
||||
copy.myDirToInfoMap.remove(dir);
|
||||
copy.setPackageName(dir, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,8 +260,12 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
|
||||
|
||||
|
||||
private void switchFromStubToAST(ASTNode root, final Iterator<StubElement<?>> stubs) {
|
||||
final IElementType contentElementType = getContentElementType();
|
||||
if (!(contentElementType instanceof IStubFileElementType)) {
|
||||
throw new AssertionError("Invalid content element type: " + contentElementType + "; elementType=" + myElementType + "; file=" + getClass() + "; viewProvider=" + getViewProvider());
|
||||
}
|
||||
((TreeElement)root).acceptTree(new RecursiveTreeElementWalkingVisitor() {
|
||||
final StubBuilder builder = ((IStubFileElementType)getContentElementType()).getBuilder();
|
||||
final StubBuilder builder = ((IStubFileElementType)contentElementType).getBuilder();
|
||||
|
||||
@Override
|
||||
protected void visitNode(TreeElement tree) {
|
||||
@@ -624,6 +628,8 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
|
||||
|
||||
@Nullable
|
||||
private StubTree derefStub() {
|
||||
if (myStub == null) return null;
|
||||
|
||||
synchronized (myStubLock) {
|
||||
return myStub != null ? myStub.get() : null;
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ public class PsiProximityComparator implements Comparator<Object> {
|
||||
};
|
||||
private static final Key<Module> MODULE_BY_LOCATION = Key.create("ModuleByLocation");
|
||||
|
||||
public PsiProximityComparator(PsiElement context) {
|
||||
public PsiProximityComparator(@Nullable PsiElement context) {
|
||||
myContext = context;
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ public class PsiProximityComparator implements Comparator<Object> {
|
||||
return - proximity1.compareTo(proximity2);
|
||||
}
|
||||
|
||||
if (myContext == null) return 0;
|
||||
Module contextModule = ModuleUtil.findModuleForPsiElement(myContext);
|
||||
if (contextModule == null) return 0;
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ public class DiffToolbarComponent extends JPanel {
|
||||
public void resetToolbar(DiffRequest.ToolbarAddons toolBar) {
|
||||
if (myToolbar != null) remove(myToolbar.getComponent());
|
||||
myToolbar = new DiffToolbarImpl();
|
||||
myToolbar.setTargetComponent(myWholeComponent);
|
||||
myToolbar.reset(toolBar);
|
||||
myToolbar.registerKeyboardActions(myWholeComponent);
|
||||
add(myToolbar.getComponent(), BorderLayout.CENTER);
|
||||
|
||||
@@ -25,6 +25,7 @@ import javax.swing.*;
|
||||
public class DiffToolbarImpl implements DiffToolbar {
|
||||
private final DefaultActionGroup myActionGroup = new DefaultActionGroup();
|
||||
private ActionToolbar myActionToolbar;
|
||||
private JComponent myTargetComponent;
|
||||
|
||||
public void registerKeyboardActions(JComponent registerActionsTo) {
|
||||
AnAction[] actions = getAllActions();
|
||||
@@ -54,9 +55,11 @@ public class DiffToolbarImpl implements DiffToolbar {
|
||||
}
|
||||
|
||||
public JComponent getComponent() {
|
||||
if (myActionToolbar == null)
|
||||
if (myActionToolbar == null) {
|
||||
myActionToolbar = ActionManager.getInstance().
|
||||
createActionToolbar(ActionPlaces.UNKNOWN, myActionGroup, true);
|
||||
myActionToolbar.setTargetComponent(myTargetComponent);
|
||||
}
|
||||
return myActionToolbar.getComponent();
|
||||
}
|
||||
|
||||
@@ -78,4 +81,11 @@ public class DiffToolbarImpl implements DiffToolbar {
|
||||
myActionGroup.removeAll();
|
||||
toolBar.customize(this);
|
||||
}
|
||||
|
||||
public void setTargetComponent(JComponent component) {
|
||||
myTargetComponent = component;
|
||||
if (myActionToolbar != null) {
|
||||
myActionToolbar.setTargetComponent(component);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -433,7 +433,7 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
|
||||
final byte[] content = delegate.contentsToByteArray(file);
|
||||
|
||||
ApplicationEx application = (ApplicationEx)ApplicationManager.getApplication();
|
||||
if ((cacheContent && !delegate.isReadOnly() || (!application.isInternal() && !application.isUnitTestMode())) &&
|
||||
if ((!delegate.isReadOnly() || (!application.isInternal() && !application.isUnitTestMode())) &&
|
||||
!noCaching && content.length <= FILE_LENGTH_TO_CACHE_THRESHOLD) {
|
||||
synchronized (INPUT_LOCK) {
|
||||
writeContent(file, content, delegate.isReadOnly());
|
||||
|
||||
@@ -58,26 +58,12 @@ import java.util.List;
|
||||
* @author: lesya
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class AnnotateToggleAction extends ToggleAction implements DumbAware {
|
||||
public class AnnotateToggleAction extends ToggleAction implements DumbAware, AnnotationColors {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.actions.AnnotateToggleAction");
|
||||
protected static final Key<Collection<ActiveAnnotationGutter>> KEY_IN_EDITOR = Key.create("Annotations");
|
||||
private final static Color[] BG_COLORS = {
|
||||
new Color(222, 241, 229),
|
||||
new Color(234, 255, 226),
|
||||
new Color(208, 229, 229),
|
||||
new Color(255, 226, 199),
|
||||
new Color(227, 226, 223),
|
||||
new Color(255, 213, 203),
|
||||
new Color(220, 204, 236),
|
||||
new Color(255, 191, 195),
|
||||
new Color(243, 223, 243),
|
||||
new Color(217, 228, 249),
|
||||
new Color(255, 251, 207),
|
||||
new Color(217, 222, 229),
|
||||
new Color(255, 204, 238),
|
||||
new Color(236, 236, 236)};
|
||||
|
||||
public void update(AnActionEvent e) {
|
||||
super.update(e);
|
||||
final boolean enabled = isEnabled(VcsContextFactory.SERVICE.getInstance().createContextOn(e));
|
||||
e.getPresentation().setEnabled(enabled);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.openapi.vcs.actions;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public interface AnnotationColors {
|
||||
Color[] BG_COLORS = {
|
||||
new Color(222, 241, 229),
|
||||
new Color(234, 255, 226),
|
||||
new Color(208, 229, 229),
|
||||
new Color(255, 226, 199),
|
||||
new Color(227, 226, 223),
|
||||
new Color(255, 213, 203),
|
||||
new Color(220, 204, 236),
|
||||
new Color(255, 191, 195),
|
||||
new Color(243, 223, 243),
|
||||
new Color(217, 228, 249),
|
||||
new Color(255, 251, 207),
|
||||
new Color(217, 222, 229),
|
||||
new Color(255, 204, 238),
|
||||
new Color(236, 236, 236)
|
||||
};
|
||||
}
|
||||
@@ -816,7 +816,7 @@ set.replaceable.by.enum.set.display.name=Set replaceable with EnumSet
|
||||
non.static.inner.class.in.secure.context.display.name=Non-static inner class in secure context
|
||||
tail.recursion.display.name=Tail recursion
|
||||
finally.block.cannot.complete.normally.display.name='finally' block which can not complete normally
|
||||
arithmetic.on.volatile.field.display.name=Arithmetic operation on volatile field
|
||||
non.atomic.operation.on.volatile.field.display.name=Non-atomic operation on volatile field
|
||||
public.static.collection.field.display.name='public static' collection field
|
||||
non.exception.name.ends.with.exception.display.name=Non-exception class name ends with 'Exception'
|
||||
synchronized.method.display.name='synchronized' method
|
||||
@@ -993,7 +993,7 @@ serializable.inner.class.has.serial.version.uid.field.problem.descriptor=Inner c
|
||||
serializable.inner.class.with.non.serializable.outer.class.problem.descriptor=Inner class <code>#ref</code> is serializable while its outer class is not #loc
|
||||
busy.wait.problem.descriptor=Call to <code>Thread.#ref()</code> in a loop, probably busy-waiting #loc
|
||||
sleep.while.holding.lock.problem.descriptor=Call to <code>Thread.#ref()</code> while synchronized #loc
|
||||
arithmetic.on.volatile.field.problem.descriptor=Arithmetic operation on volatile field <code>#ref</code> #loc
|
||||
non.atomic.operation.on.volatile.field.problem.descriptor=Non-atomic operation on volatile field <code>#ref</code> #loc
|
||||
call.to.native.method.while.locked.problem.descriptor=Call to native method <code>#ref()</code> in a synchronized context #loc
|
||||
object.notify.problem.descriptor=<code>#ref</code> should probably be replaced with 'notifyAll()' #loc
|
||||
condition.signal.problem.descriptor=<code>#ref</code> should probably be replaced with 'signalAll()' #loc
|
||||
|
||||
@@ -821,7 +821,6 @@ public class InspectionGadgetsPlugin implements ApplicationComponent,
|
||||
private void registerThreadingInspections() {
|
||||
m_inspectionClasses.add(AccessToNonThreadSafeStaticFieldFromInstanceInspection.class);
|
||||
m_inspectionClasses.add(AccessToStaticFieldLockedOnInstanceInspection.class);
|
||||
m_inspectionClasses.add(ArithmeticOnVolatileFieldInspection.class);
|
||||
m_inspectionClasses.add(AwaitNotInLoopInspection.class);
|
||||
m_inspectionClasses.add(AwaitWithoutCorrespondingSignalInspection.class);
|
||||
m_inspectionClasses.add(BusyWaitInspection.class);
|
||||
@@ -834,6 +833,7 @@ public class InspectionGadgetsPlugin implements ApplicationComponent,
|
||||
m_inspectionClasses.add(MethodMayBeSynchronizedInspection.class);
|
||||
m_inspectionClasses.add(NakedNotifyInspection.class);
|
||||
m_inspectionClasses.add(NestedSynchronizedStatementInspection.class);
|
||||
m_inspectionClasses.add(NonAtomicOperationOnVolatileFieldInspection.class);
|
||||
m_inspectionClasses.add(NonSynchronizedMethodOverridesSynchronizedMethodInspection.class);
|
||||
m_inspectionClasses.add(NotifyCalledOnConditionInspection.class);
|
||||
m_inspectionClasses.add(NotifyNotInSynchronizedContextInspection.class);
|
||||
|
||||
-105
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright 2003-2007 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* 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.siyeh.ig.threading;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.psiutils.WellFormednessUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ArithmeticOnVolatileFieldInspection extends BaseInspection {
|
||||
|
||||
@NotNull
|
||||
public String getDisplayName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"arithmetic.on.volatile.field.display.name");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected String buildErrorString(Object... infos) {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"arithmetic.on.volatile.field.problem.descriptor");
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor buildVisitor() {
|
||||
return new AritmeticOnVolatileFieldInspection();
|
||||
}
|
||||
|
||||
private static class AritmeticOnVolatileFieldInspection
|
||||
extends BaseInspectionVisitor {
|
||||
|
||||
@Override public void visitBinaryExpression(
|
||||
@NotNull PsiBinaryExpression expression) {
|
||||
super.visitBinaryExpression(expression);
|
||||
if (expression.getROperand() == null) {
|
||||
return;
|
||||
}
|
||||
final PsiJavaToken sign = expression.getOperationSign();
|
||||
final IElementType tokenType = sign.getTokenType();
|
||||
if (!JavaTokenType.ASTERISK.equals(tokenType) &&
|
||||
!JavaTokenType.DIV.equals(tokenType) &&
|
||||
!JavaTokenType.PLUS.equals(tokenType) &&
|
||||
!JavaTokenType.MINUS.equals(tokenType) &&
|
||||
!JavaTokenType.PERC.equals(tokenType)) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression lhs = expression.getLOperand();
|
||||
checkForVolatile(lhs);
|
||||
final PsiExpression rhs = expression.getROperand();
|
||||
checkForVolatile(rhs);
|
||||
}
|
||||
|
||||
@Override public void visitAssignmentExpression(
|
||||
@NotNull PsiAssignmentExpression expression) {
|
||||
super.visitAssignmentExpression(expression);
|
||||
if (!WellFormednessUtils.isWellFormed(expression)) {
|
||||
return;
|
||||
}
|
||||
final PsiJavaToken sign = expression.getOperationSign();
|
||||
final IElementType tokenType = sign.getTokenType();
|
||||
if (!JavaTokenType.ASTERISKEQ.equals(tokenType) &&
|
||||
!JavaTokenType.DIVEQ.equals(tokenType) &&
|
||||
!JavaTokenType.PLUSEQ.equals(tokenType) &&
|
||||
!JavaTokenType.MINUSEQ.equals(tokenType) &&
|
||||
!JavaTokenType.PERCEQ.equals(tokenType)) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression lhs = expression.getLExpression();
|
||||
checkForVolatile(lhs);
|
||||
final PsiExpression rhs = expression.getRExpression();
|
||||
checkForVolatile(rhs);
|
||||
}
|
||||
|
||||
private void checkForVolatile(PsiExpression expression) {
|
||||
if (!(expression instanceof PsiReferenceExpression)) {
|
||||
return;
|
||||
}
|
||||
final PsiReferenceExpression reference =
|
||||
(PsiReferenceExpression)expression;
|
||||
final PsiElement referent = reference.resolve();
|
||||
if (!(referent instanceof PsiField)) {
|
||||
return;
|
||||
}
|
||||
final PsiField field = (PsiField)referent;
|
||||
if (field.hasModifierProperty(PsiModifier.VOLATILE)) {
|
||||
registerError(expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2003-2010 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* 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.siyeh.ig.threading;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.psiutils.VariableAccessUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class NonAtomicOperationOnVolatileFieldInspection
|
||||
extends BaseInspection {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getDisplayName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"non.atomic.operation.on.volatile.field.display.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected String buildErrorString(Object... infos) {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"non.atomic.operation.on.volatile.field.problem.descriptor");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseInspectionVisitor buildVisitor() {
|
||||
return new NonAtomicOperationOnVolatileFieldVisitor();
|
||||
}
|
||||
|
||||
private static class NonAtomicOperationOnVolatileFieldVisitor
|
||||
extends BaseInspectionVisitor {
|
||||
|
||||
@Override public void visitAssignmentExpression(
|
||||
@NotNull PsiAssignmentExpression expression) {
|
||||
super.visitAssignmentExpression(expression);
|
||||
final PsiExpression rhs = expression.getRExpression();
|
||||
if (rhs == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression lhs = expression.getLExpression();
|
||||
final PsiField volatileField = findVolatileField(lhs);
|
||||
if (volatileField == null) {
|
||||
return;
|
||||
}
|
||||
final IElementType tokenType = expression.getOperationTokenType();
|
||||
if (tokenType.equals(JavaTokenType.PLUSEQ) ||
|
||||
tokenType.equals(JavaTokenType.MINUSEQ) ||
|
||||
tokenType.equals(JavaTokenType.ASTERISKEQ) ||
|
||||
tokenType.equals(JavaTokenType.DIVEQ) ||
|
||||
tokenType.equals(JavaTokenType.ANDEQ) ||
|
||||
tokenType.equals(JavaTokenType.OREQ)||
|
||||
tokenType.equals(JavaTokenType.XOREQ)||
|
||||
tokenType.equals(JavaTokenType.PERCEQ)||
|
||||
tokenType.equals(JavaTokenType.LTLTEQ)||
|
||||
tokenType.equals(JavaTokenType.GTGTEQ)||
|
||||
tokenType.equals(JavaTokenType.GTGTGTEQ)) {
|
||||
registerError(lhs);
|
||||
return;
|
||||
}
|
||||
if (VariableAccessUtils.variableIsUsed(volatileField, rhs)) {
|
||||
registerError(lhs);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPrefixExpression(PsiPrefixExpression expression) {
|
||||
super.visitPrefixExpression(expression);
|
||||
final PsiExpression operand = expression.getOperand();
|
||||
if (operand == null) {
|
||||
return;
|
||||
}
|
||||
final PsiField volatileField = findVolatileField(operand);
|
||||
if (volatileField == null) {
|
||||
return;
|
||||
}
|
||||
registerError(operand);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPostfixExpression(PsiPostfixExpression expression) {
|
||||
super.visitPostfixExpression(expression);
|
||||
final PsiExpression operand = expression.getOperand();
|
||||
final PsiField volatileField = findVolatileField(operand);
|
||||
if (volatileField == null) {
|
||||
return;
|
||||
}
|
||||
registerError(operand);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiField findVolatileField(PsiExpression expression) {
|
||||
if (!(expression instanceof PsiReferenceExpression)) {
|
||||
return null;
|
||||
}
|
||||
final PsiReferenceExpression reference =
|
||||
(PsiReferenceExpression)expression;
|
||||
final PsiElement referent = reference.resolve();
|
||||
if (!(referent instanceof PsiField)) {
|
||||
return null;
|
||||
}
|
||||
final PsiField field = (PsiField)referent;
|
||||
if (!field.hasModifierProperty(PsiModifier.VOLATILE)) {
|
||||
return null;
|
||||
}
|
||||
return field;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<html>
|
||||
<body><table> <tr> <td valign="top" height="150">
|
||||
<font face="verdana" size="-1">
|
||||
This inspection reports any uses of volatile fields in arithmetic operations.
|
||||
It's a common misconception that such operations are effectively atomic, but the
|
||||
Java Memory Model only specifies that loads and stores on volatile variables are
|
||||
atomic. This can lead to unexpected results, including lost updates, when using
|
||||
volatile fields in arithmetic operations.
|
||||
</font></td> </tr> <tr> <td height="20"> <font face="verdana" size="-2">Powered by InspectionGadgets </font> </td> </tr> </table> </body>
|
||||
</html>
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
<html>
|
||||
<body><table> <tr> <td valign="top" height="150">
|
||||
<font face="verdana" size="-1">
|
||||
This inspection reports any non-atomic operations on volatile fields. Non-atomic
|
||||
operations on volatile fields are operations where the volatile field is read and
|
||||
the value is used to update the volatile field. It is possible for the value of the
|
||||
field to change between the read and write, making the operation possibly invalid.
|
||||
In such cases it is better to use one of the <b><font
|
||||
color="#000080">Atomic*</font></b> or
|
||||
<b><font color="#000080">Atomic*FieldUpdater</font></b> classes
|
||||
from the <b><font color="#000080">java.util.concurrent.atomic</font></b> package.
|
||||
</font></td> </tr> <tr> <td height="20"> <font face="verdana" size="-2">New in 10, Powered by InspectionGadgets</font> </td> </tr> </table> </body>
|
||||
</html>
|
||||
@@ -135,6 +135,7 @@ public class GitStashUtils {
|
||||
shelveManager
|
||||
.unshelveChangeList(shelvedChangeList, shelvedChangeList.getChanges(), shelvedChangeList.getBinaryFiles(),
|
||||
changeManager.getDefaultChangeList(), false);
|
||||
shelveManager.deleteChangeList(shelvedChangeList);
|
||||
}
|
||||
finally {
|
||||
l.setEventsSuppressed(false);
|
||||
|
||||
@@ -31,7 +31,7 @@ import java.util.regex.Pattern;
|
||||
*/
|
||||
public class GroovyNamesUtil {
|
||||
|
||||
private static final Pattern PATTERN = Pattern.compile("[A-Za-z][a-z]*");
|
||||
private static final Pattern PATTERN = Pattern.compile("[A-Za-z][a-z0-9]*");
|
||||
|
||||
private GroovyNamesUtil() {
|
||||
}
|
||||
|
||||
@@ -82,7 +82,9 @@ public class PhysicalDomParentStrategy implements DomParentStrategy {
|
||||
final XmlElement thatElement = ((PhysicalDomParentStrategy)o).myElement;
|
||||
if (xmlElementsEqual(myElement, thatElement)) {
|
||||
if (myElement != thatElement) {
|
||||
assert myElement.getNavigationElement() == thatElement.getNavigationElement();
|
||||
final PsiElement nav1 = myElement.getNavigationElement();
|
||||
final PsiElement nav2 = thatElement.getNavigationElement();
|
||||
assert nav1 == nav2 : nav1 + "!=" + nav2;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user