Merge remote branch 'origin/master'

This commit is contained in:
Evgeny Zakrevsky
2012-03-19 13:32:08 +04:00
20 changed files with 309 additions and 77 deletions
@@ -79,14 +79,13 @@ import java.io.IOException;
import java.util.*;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReference;
public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
@NotNull public static final Icon ICON = IconLoader.getIcon("/modules/annotation.png");
private static final Logger LOG = Logger.getInstance("#" + ExternalAnnotationsManagerImpl.class.getName());
@NotNull private final ConcurrentMap<String, List<XmlFile>> myExternalAnnotations = new ConcurrentWeakValueHashMap<String, List<XmlFile>>();
@NotNull private final AtomicReference<ThreeState> myHasAnyAnnotationsRoots = new AtomicReference<ThreeState>(ThreeState.UNSURE);
@NotNull private volatile ThreeState myHasAnyAnnotationsRoots = ThreeState.UNSURE;
@NotNull private static final List<XmlFile> NULL = new ArrayList<XmlFile>();
private final PsiManager myPsiManager;
@@ -94,38 +93,42 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
myPsiManager = psiManager;
final MessageBusConnection connection = project.getMessageBus().connect(project);
connection.subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootListener() {
@Override
public void beforeRootsChange(ModuleRootEvent event) {
}
@Override
public void rootsChanged(ModuleRootEvent event) {
myExternalAnnotations.clear();
myHasAnyAnnotationsRoots.set(ThreeState.UNSURE);
myHasAnyAnnotationsRoots = ThreeState.UNSURE;
}
});
}
private ThreeState hasAnyAnnotationsRoots() {
if (myHasAnyAnnotationsRoots.get() == ThreeState.UNSURE) {
if (myHasAnyAnnotationsRoots == ThreeState.UNSURE) {
final Module[] modules = ModuleManager.getInstance(myPsiManager.getProject()).getModules();
for (Module module : modules) {
for (OrderEntry entry : ModuleRootManager.getInstance(module).getOrderEntries()) {
final String[] urls = AnnotationOrderRootType.getUrls(entry);
if (urls.length > 0) {
myHasAnyAnnotationsRoots.set(ThreeState.YES);
myHasAnyAnnotationsRoots = ThreeState.YES;
return ThreeState.YES;
}
}
}
myHasAnyAnnotationsRoots.set(ThreeState.NO);
myHasAnyAnnotationsRoots = ThreeState.NO;
}
return myHasAnyAnnotationsRoots.get();
return myHasAnyAnnotationsRoots;
}
@Override
@Nullable
public PsiAnnotation findExternalAnnotation(@NotNull final PsiModifierListOwner listOwner, @NotNull final String annotationFQN) {
return collectExternalAnnotations(listOwner).get(annotationFQN);
}
@Override
@Nullable
public PsiAnnotation[] findExternalAnnotations(@NotNull final PsiModifierListOwner listOwner) {
final Map<String, PsiAnnotation> result = collectExternalAnnotations(listOwner);
@@ -135,11 +138,11 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
@NotNull
private Map<String, PsiAnnotation> collectExternalAnnotations(@NotNull final PsiModifierListOwner listOwner) {
if (hasAnyAnnotationsRoots() == ThreeState.NO) return Collections.emptyMap();
final Map<String, PsiAnnotation> result = new HashMap<String, PsiAnnotation>();
final List<XmlFile> files = findExternalAnnotationsFile(listOwner);
final List<XmlFile> files = findExternalAnnotationsFiles(listOwner);
if (files == null) {
return Collections.emptyMap();
}
final Map<String, PsiAnnotation> result = new HashMap<String, PsiAnnotation>();
for (XmlFile file : files) {
if (!file.isValid()) continue;
final XmlDocument document = file.getDocument();
@@ -168,7 +171,7 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
"@" + annotationFQN + (buf.length() > 0 ? "(" + StringUtil.trimStart(buf.toString(), ",") + ")" : "");
try {
result.put(annotationFQN,
JavaPsiFacade.getInstance(listOwner.getProject()).getElementFactory().createAnnotationFromText(
JavaPsiFacade.getInstance(myPsiManager.getProject()).getElementFactory().createAnnotationFromText(
annotationText, null));
}
catch (IncorrectOperationException e) {
@@ -186,11 +189,12 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
}
@Override
public void annotateExternally(@NotNull final PsiModifierListOwner listOwner,
@NotNull final String annotationFQName,
@NotNull final PsiFile fromFile,
final PsiNameValuePair[] value) {
final Project project = listOwner.getProject();
final Project project = myPsiManager.getProject();
final PsiFile containingFile = listOwner.getContainingFile();
if (!(containingFile instanceof PsiJavaFile)) {
return;
@@ -215,6 +219,7 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
return;
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
setupRootAndAnnotateExternally(entry, project, listOwner, annotationFQName, fromFile, packageName, virtualFile, value);
}
@@ -240,9 +245,10 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
return;
}
new WriteCommandAction(project) {
@Override
protected void run(final Result result) throws Throwable {
appendChosenAnnotationsRoot(entry, file);
final List<XmlFile> xmlFiles = findExternalAnnotationsFile(listOwner);
final List<XmlFile> xmlFiles = findExternalAnnotationsFiles(listOwner);
if (xmlFiles != null) { //file already exists under appeared content root
if (!CodeInsightUtilBase.preparePsiElementForWrite(xmlFiles.get(0))) return;
annotateExternally(listOwner, annotationFQName, xmlFiles.get(0), fromFile, value);
@@ -314,7 +320,7 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
@NotNull final PsiFile fromFile,
final PsiNameValuePair[] value) {
final XmlFile[] annotationsXml = new XmlFile[1];
List<XmlFile> xmlFiles = findExternalAnnotationsFile(listOwner);
List<XmlFile> xmlFiles = findExternalAnnotationsFiles(listOwner);
if (xmlFiles != null) {
for (XmlFile xmlFile : xmlFiles) {
final VirtualFile vXmlFile = xmlFile.getVirtualFile();
@@ -330,6 +336,7 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
final List<XmlFile> annotationFiles = new ArrayList<XmlFile>(xmlFiles);
new WriteCommandAction(project) {
@Override
protected void run(final Result result) throws Throwable {
if (annotationsXml[0] == null) {
annotationsXml[0] = createAnnotationsXml(file, packageName);
@@ -343,8 +350,9 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
}.execute();
}
@Override
public boolean deannotate(@NotNull final PsiModifierListOwner listOwner, @NotNull final String annotationFQN) {
final List<XmlFile> files = findExternalAnnotationsFile(listOwner);
final List<XmlFile> files = findExternalAnnotationsFiles(listOwner);
if (files != null) {
for (XmlFile file : files) {
if (file.isValid()) {
@@ -359,7 +367,7 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
if (Comparing.strEqual(className, externalName) || Comparing.strEqual(className, oldExternalName)) {
for (XmlTag annotationTag : tag.getSubTags()) {
if (Comparing.strEqual(annotationTag.getAttributeValue("name"), annotationFQN)) {
if (ReadonlyStatusHandler.getInstance(file.getProject())
if (ReadonlyStatusHandler.getInstance(myPsiManager.getProject())
.ensureFilesWritable(file.getVirtualFile()).hasReadonlyFiles()) {
return false;
}
@@ -386,11 +394,12 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
return false;
}
@Override
@NotNull
public AnnotationPlace chooseAnnotationsPlace(@NotNull final PsiElement element) {
if (!element.isPhysical()) return AnnotationPlace.IN_CODE; //element just created
if (!element.getManager().isInProject(element)) return AnnotationPlace.EXTERNAL;
final Project project = element.getProject();
final Project project = myPsiManager.getProject();
final PsiFile containingFile = element.getContainingFile();
final VirtualFile virtualFile = containingFile.getVirtualFile();
LOG.assertTrue(virtualFile != null);
@@ -472,7 +481,7 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
myExternalAnnotations.clear();
}
private static void annotateExternally(final PsiModifierListOwner listOwner,
private void annotateExternally(final PsiModifierListOwner listOwner,
final String annotationFQName,
@Nullable final XmlFile xmlFile,
@NotNull PsiFile codeUsageFile,
@@ -492,7 +501,8 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
break;
}
}
tag.add(XmlElementFactory.getInstance(xmlFile.getProject()).createTagFromText(createAnnotationTag(annotationFQName, values)));
tag.add(XmlElementFactory.getInstance(myPsiManager.getProject()).createTagFromText(
createAnnotationTag(annotationFQName, values)));
return;
}
}
@@ -500,7 +510,7 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
"<item name=\'" + externalName + "\'>\n";
text += createAnnotationTag(annotationFQName, values);
text += "</item>";
rootTag.add(XmlElementFactory.getInstance(xmlFile.getProject()).createTagFromText(text));
rootTag.add(XmlElementFactory.getInstance(myPsiManager.getProject()).createTagFromText(text));
}
}
}
@@ -520,13 +530,13 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
if (values != null) {
text = " <annotation name=\'" + annotationFQName + "\'>\n";
text += StringUtil.join(values, new Function<PsiNameValuePair, String>() {
@NonNls
@NotNull
@Override
public String fun(@NotNull PsiNameValuePair pair) {
if (pair.getName() != null) {
return "<val name=\"" + pair.getName() + "\" val=\"" + StringUtil.escapeXml(pair.getValue().getText()) + "\"/>";
}
return "<val val=\"" + StringUtil.escapeXml(pair.getValue().getText()) + "\"/>";
return "<val" +
(pair.getName() != null ? " name=\"" + pair.getName() + "\"" : "") +
" val=\"" + StringUtil.escapeXml(pair.getValue().getText()) + "\"/>";
}
}, " \n");
text += " </annotation>";
@@ -572,8 +582,8 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
}
@Nullable
private List<XmlFile> findExternalAnnotationsFile(@NotNull PsiModifierListOwner listOwner) {
final Project project = listOwner.getProject();
private List<XmlFile> findExternalAnnotationsFiles(@NotNull PsiModifierListOwner listOwner) {
final Project project = myPsiManager.getProject();
final PsiFile containingFile = listOwner.getContainingFile();
if (!(containingFile instanceof PsiJavaFile)) {
return null;
@@ -672,15 +682,18 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
init();
}
@Override
protected String getOkActionName() {
return ADD_IN_CODE;
}
@Override
@NotNull
protected String getCancelActionName() {
return CommonBundle.getCancelButtonText();
}
@Override
@NotNull
@SuppressWarnings({"NonStaticInitializer"})
protected Action[] createActions() {
@@ -692,6 +705,7 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
assignMnemonic(externalName, this);
}
@Override
public void actionPerformed(final ActionEvent e) {
if (canBeHidden()) {
setToBeShown(toBeShown(), true);
@@ -701,20 +715,24 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
}, getCancelAction()};
}
@Override
protected boolean isToBeShown() {
return CodeStyleSettingsManager.getSettings(myProject).USE_EXTERNAL_ANNOTATIONS;
}
@Override
protected void setToBeShown(boolean value, boolean onOk) {
CodeStyleSettingsManager.getSettings(myProject).USE_EXTERNAL_ANNOTATIONS = value;
}
@Override
protected JComponent createNorthPanel() {
final JPanel northPanel = (JPanel)super.createNorthPanel();
northPanel.add(new JLabel(MESSAGE), BorderLayout.CENTER);
return northPanel;
}
@Override
protected boolean shouldSaveOptionsOnCancel() {
return true;
}
@@ -33,8 +33,6 @@ public class UnscrambleListener implements ApplicationActivationListener {
@Override
public void applicationActivated(final IdeFrame ideFrame) {
if (SystemInfo.isMac) return;
final Runnable processClipboard = new Runnable() {
@Override
public void run() {
@@ -44,7 +44,7 @@ public abstract class JavaCodeInsightFixtureTestCase extends UsefulTestCase{
protected void setUp() throws Exception {
super.setUp();
final TestFixtureBuilder<IdeaProjectTestFixture> projectBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder();
final TestFixtureBuilder<IdeaProjectTestFixture> projectBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getName());
myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(projectBuilder.getFixture());
final JavaModuleFixtureBuilder moduleFixtureBuilder = projectBuilder.addModule(JavaModuleFixtureBuilder.class);
moduleFixtureBuilder.addSourceContentRoot(myFixture.getTempDirPath());
@@ -15,6 +15,8 @@
*/
package com.intellij.testFramework.fixtures;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
@@ -41,8 +43,15 @@ public abstract class JavaTestFixtureFactory {
public abstract JavaCodeInsightTestFixture createCodeInsightFixture(IdeaProjectTestFixture projectFixture, TempDirTestFixture tempDirFixture);
/**
*
* @deprecated use {@link JavaTestFixtureFactory#createFixtureBuilder(String)}
*/
//also implicitly initializes ourInstance and registers java module fixture builder
public static TestFixtureBuilder<IdeaProjectTestFixture> createFixtureBuilder() {
return IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder();
}
public static TestFixtureBuilder<IdeaProjectTestFixture> createFixtureBuilder(@NotNull String name) {
return IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(name);
}
}
@@ -22,6 +22,7 @@ import java.util.List;
public abstract class CustomFoldingBuilder extends FoldingBuilderEx implements DumbAware {
private CustomFoldingProvider myDefaultProvider;
private static final int MAX_LOOKUP_DEPTH = 10;
@NotNull
@Override
@@ -29,7 +30,7 @@ public abstract class CustomFoldingBuilder extends FoldingBuilderEx implements D
List<FoldingDescriptor> descriptors = new ArrayList<FoldingDescriptor>();
if (CustomFoldingProvider.getAllProviders().length > 0) {
myDefaultProvider = null;
addCustomFoldingRegionsRecursively(null, root.getNode(), descriptors);
addCustomFoldingRegionsRecursively(null, root.getNode(), descriptors, 0);
}
buildLanguageFoldRegions(descriptors, root, document, quick);
return descriptors.toArray(new FoldingDescriptor[descriptors.size()]);
@@ -57,7 +58,8 @@ public abstract class CustomFoldingBuilder extends FoldingBuilderEx implements D
private void addCustomFoldingRegionsRecursively(@Nullable FoldingStack foldingStack,
@NotNull ASTNode node,
List<FoldingDescriptor> descriptors) {
List<FoldingDescriptor> descriptors,
int currDepth) {
FoldingStack localFoldingStack = isCustomFoldingRoot(node) || foldingStack == null ? new FoldingStack(node) : foldingStack;
for (ASTNode child = node.getFirstChildNode(); child != null; child = child.getTreeNext()) {
if (isCustomRegionStart(child)) {
@@ -72,7 +74,9 @@ public abstract class CustomFoldingBuilder extends FoldingBuilderEx implements D
}
}
else {
addCustomFoldingRegionsRecursively(localFoldingStack, child, descriptors);
if (currDepth < MAX_LOOKUP_DEPTH) {
addCustomFoldingRegionsRecursively(localFoldingStack, child, descriptors, currDepth + 1);
}
}
}
}
@@ -61,6 +61,7 @@ import com.intellij.psi.impl.PsiDocumentManagerImpl;
import com.intellij.psi.search.scope.packageSet.NamedScope;
import com.intellij.psi.search.scope.packageSet.NamedScopeManager;
import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.Alarm;
import com.intellij.util.CommonProcessors;
import com.intellij.util.Processor;
@@ -94,7 +95,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
private final Alarm myAlarm = new Alarm();
private boolean myUpdateByTimerEnabled = true;
private final Collection<VirtualFile> myDisabledHintsFiles = new THashSet<VirtualFile>();
private final Collection<PsiFile> myDisabledHighlightingFiles = new THashSet<PsiFile>();
private final Collection<VirtualFile> myDisabledHighlightingFiles = new THashSet<VirtualFile>();
private final FileStatusMap myFileStatusMap;
private DaemonCodeAnalyzerSettings myLastSettings;
@@ -122,6 +123,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
myFileStatusMap = new FileStatusMap(myProject);
myPassExecutorService = new PassExecutorService(myProject) {
@Override
protected void afterApplyInformationToEditor(final TextEditorHighlightingPass pass,
final FileEditor fileEditor,
final ProgressIndicator updateProgress) {
@@ -132,6 +134,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
}
}
@Override
protected boolean isDisposed() {
return myDisposed || super.isDisposed();
}
@@ -283,14 +286,17 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
myPassExecutorService.cancelAll(true);
}
@Override
@NotNull
public String getComponentName() {
return "DaemonCodeAnalyzer";
}
@Override
public void initComponent() {
}
@Override
public void disposeComponent() {
}
@@ -309,6 +315,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
myFileStatusMap.markAllFilesDirty();
}
@Override
public void projectClosed() {
assert myInitialized : "Disposing not initialized component";
assert !myDisposed : "Double dispose";
@@ -354,6 +361,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
return myScopes;
}
@Override
public void settingsChanged() {
DaemonCodeAnalyzerSettings settings = DaemonCodeAnalyzerSettings.getInstance();
if (settings.isCodeHighlightingChanged(myLastSettings)) {
@@ -362,11 +370,13 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
myLastSettings = (DaemonCodeAnalyzerSettings)settings.clone();
}
@Override
public void updateVisibleHighlighters(@NotNull Editor editor) {
ApplicationManager.getApplication().assertIsDispatchThread();
// no need, will not work anyway
}
@Override
public void setUpdateByTimerEnabled(boolean value) {
myUpdateByTimerEnabled = value;
stopProcess(value);
@@ -376,6 +386,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
return myUpdateByTimerEnabled;
}
@Override
public void setImportHintsEnabled(@NotNull PsiFile file, boolean value) {
VirtualFile vFile = file.getVirtualFile();
if (value) {
@@ -388,23 +399,27 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
}
}
@Override
public void resetImportHintsEnabledForProject() {
myDisabledHintsFiles.clear();
}
@Override
public void setHighlightingEnabled(@NotNull PsiFile file, boolean value) {
VirtualFile virtualFile = PsiUtilCore.getVirtualFile(file);
if (value) {
myDisabledHighlightingFiles.remove(file);
myDisabledHighlightingFiles.remove(virtualFile);
}
else {
myDisabledHighlightingFiles.add(file);
myDisabledHighlightingFiles.add(virtualFile);
}
}
@Override
public boolean isHighlightingAvailable(PsiFile file) {
if (myDisabledHighlightingFiles.contains(file)) return false;
if (file == null || !file.isPhysical()) return false;
if (myDisabledHighlightingFiles.contains(PsiUtilCore.getVirtualFile(file))) return false;
if (file instanceof PsiCompiledElement) return false;
final FileType fileType = file.getFileType();
if (fileType == StdFileTypes.GUI_DESIGNER_FORM){
@@ -414,14 +429,17 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
return !fileType.isBinary();
}
@Override
public boolean isImportHintsEnabled(@NotNull PsiFile file) {
return isAutohintsAvailable(file) && !myDisabledHintsFiles.contains(file.getVirtualFile());
}
@Override
public boolean isAutohintsAvailable(PsiFile file) {
return isHighlightingAvailable(file) && !(file instanceof PsiCompiledElement);
}
@Override
public void restart() {
myFileStatusMap.markAllFilesDirty();
stopProcess(true);
@@ -507,6 +525,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
final SeverityRegistrar severityRegistrar = SeverityRegistrar.getInstance(project);
MarkupModelEx model = (MarkupModelEx)DocumentMarkupModel.forDocument(document, project, true);
return model.processRangeHighlightersOverlappingWith(startOffset, endOffset, new Processor<RangeHighlighterEx>() {
@Override
public boolean process(RangeHighlighterEx marker) {
Object tt = marker.getErrorStripeTooltip();
if (!(tt instanceof HighlightInfo)) return true;
@@ -529,6 +548,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
final SeverityRegistrar severityRegistrar = SeverityRegistrar.getInstance(project);
MarkupModelEx model = (MarkupModelEx)DocumentMarkupModel.forDocument(document, project, true);
return model.processRangeHighlightersOutside(startOffset, endOffset, new Processor<RangeHighlighterEx>() {
@Override
public boolean process(RangeHighlighterEx marker) {
Object tt = marker.getErrorStripeTooltip();
if (!(tt instanceof HighlightInfo)) return true;
@@ -548,6 +568,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
final boolean includeFixRange,
@NotNull final Processor<HighlightInfo> processor) {
return processHighlights(document, project, null, 0, document.getTextLength(), new Processor<HighlightInfo>() {
@Override
public boolean process(HighlightInfo info) {
if (!isOffsetInsideHighlightInfo(offset, info, includeFixRange)) return true;
@@ -561,6 +582,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
public HighlightInfo findHighlightByOffset(Document document, final int offset, final boolean includeFixRange) {
final List<HighlightInfo> foundInfoList = new SmartList<HighlightInfo>();
processHighlightsNearOffset(document, myProject, HighlightSeverity.INFORMATION, offset, includeFixRange, new Processor<HighlightInfo>() {
@Override
public boolean process(HighlightInfo info) {
if (!foundInfoList.isEmpty()) {
HighlightInfo foundInfo = foundInfoList.get(0);
@@ -635,6 +657,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
return myLastIntentionHint;
}
@Override
public void writeExternal(Element parentNode) throws WriteExternalException {
Element disableHintsElement = new Element(DISABLE_HINTS_TAG);
parentNode.addContent(disableHintsElement);
@@ -654,6 +677,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
}
}
@Override
public void readExternal(Element parentNode) throws InvalidDataException {
myDisabledHintsFiles.clear();
@@ -675,12 +699,14 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
private Runnable createUpdateRunnable() {
return new Runnable() {
@Override
public void run() {
if (myDisposed || !myProject.isInitialized()) return;
if (PowerSaveMode.isEnabled()) return;
Editor activeEditor = FileEditorManager.getInstance(myProject).getSelectedTextEditor();
Runnable runnable = new Runnable() {
@Override
public void run() {
PassExecutorService.log(myUpdateProgress, null, "Update Runnable. myUpdateByTimerEnabled:",myUpdateByTimerEnabled," something disposed:",PowerSaveMode.isEnabled() || myDisposed || !myProject.isInitialized()," activeEditors:",myProject.isDisposed() ? null : myDaemonListeners.getSelectedEditors());
if (!myUpdateByTimerEnabled) return;
@@ -745,6 +771,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
return myDaemonListeners.canChangeFileSilently(file);
}
@Override
public void autoImportReferenceAtCursor(@NotNull Editor editor, @NotNull PsiFile file) {
for(ReferenceImporter importer: Extensions.getExtensions(ReferenceImporter.EP_NAME)) {
if (importer.autoImportReferenceAtCursor(editor, file)) break;
@@ -73,7 +73,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
private final NewVirtualFileSystem myFS;
// guarded by this
protected Object myChildren; // Either HashMap<String, VFile> or VFile[]
private Object myChildren; // Either HashMap<String, VFile> or VFile[]
public VirtualDirectoryImpl(@NotNull String name, final VirtualDirectoryImpl parent, @NotNull NewVirtualFileSystem fs, final int id) {
super(name, parent, id);
@@ -379,8 +379,9 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
@NotNull
private synchronized Collection<VirtualFile> getInDbChildren() {
if (myChildren instanceof VirtualFileSystemEntry[]) {
return Arrays.asList((VirtualFile[])myChildren);
VirtualFileSystemEntry[] children = asArray();
if (children != null) {
return Arrays.asList((VirtualFile[])children);
}
if (!ourPersistence.wereChildrenAccessed(this)) {
@@ -404,13 +405,13 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
@Override
@NotNull
public synchronized VirtualFile[] getChildren() {
if (myChildren instanceof VirtualFileSystemEntry[]) {
return (VirtualFileSystemEntry[])myChildren;
VirtualFileSystemEntry[] children = asArray();
if (children != null) {
return children;
}
Pair<String[], int[]> pair = PersistentFS.listAll(this);
final int[] childrenIds = pair.second;
VirtualFileSystemEntry[] children;
if (childrenIds.length == 0) {
children = EMPTY_ARRAY;
}
@@ -454,7 +455,10 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
@Override
public NewVirtualFile findChildByIdIfCached(int id) {
final VirtualFile[] a = asArray();
final VirtualFile[] a;
synchronized (this) {
a = asArray();
}
if (a != null) {
for (VirtualFile file : a) {
NewVirtualFile withId = (NewVirtualFile)file;
@@ -477,12 +481,15 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
return null;
}
// MUST BE CALLED UNDER this LOCK
@Nullable
private VirtualFileSystemEntry[] asArray() {
if (myChildren instanceof VirtualFileSystemEntry[]) return (VirtualFileSystemEntry[])myChildren;
Object children = myChildren;
if (children instanceof VirtualFileSystemEntry[]) return (VirtualFileSystemEntry[])children;
return null;
}
// MUST BE CALLED UNDER this LOCK
@Nullable
private Map<String, VirtualFileSystemEntry> asMap() {
if (myChildren instanceof Map) {
@@ -530,7 +537,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
}
public synchronized boolean allChildrenLoaded() {
return myChildren instanceof VirtualFileSystemEntry[];
return asArray() != null;
}
@NotNull
@@ -917,7 +917,8 @@ utility.class.without.private.constructor.problem.descriptor=Class <code>#ref</c
abstract.method.overrides.concrete.method.problem.descriptor=Abstract method <code>#ref()</code> overrides concrete method #loc
abstract.method.with.missing.implementations.problem.descriptor=Abstract method <code>#ref()</code> is not implemented in every subclass #loc
abstract.method.overrides.abstract.method.problem.descriptor=Abstract method <code>#ref()</code> overrides abstract method #loc
abstract.method.overrides.abstract.method.ignore.different.javadoc.option=Ignore methods with a different JavaDoc than their super methods
abstract.method.overrides.abstract.method.ignore.different.javadoc.option=Ignore methods with different JavaDoc than their super methods
abstract.method.overrides.abstract.method.ignore.different.annotations.option=Ignore methods with different annotations than their super methods
abstract.class.extends.concrete.class.problem.descriptor=Class <code>#ref</code> is declared 'abstract', and extends a concrete class #loc
static.non.final.field.problem.descriptor='static' non-'final' field <code>#ref</code> #loc
constant.declared.in.abstract.class.problem.descriptor=Constant <code>#ref</code> declared in abstract class #loc
@@ -1955,6 +1956,7 @@ unclear.binary.expression.problem.descriptor=Expression could use clarifying par
unclear.binary.expression.quickfix=Add clarifying parentheses
new.exception.without.arguments.display.name=Exception constructor called without arguments
new.exception.without.arguments.problem.descriptor=<code>new #ref()</code> without arguments #loc
new.exception.without.arguments.ignore.option=Ignore for exceptions that have no constructors with parameters
absolute.alignment.in.user.interface.display.name=Absolute alignment used in AWT/Swing code
absolute.alignment.in.user.interface.problem.descriptor=Absolute alignment constant <code>{0}.#ref</code> used #loc
absolute.alignment.in.user.interface.quickfix=Replace with ''{0}.{1}''
@@ -15,14 +15,22 @@
*/
package com.siyeh.ig.errorhandling;
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.siyeh.InspectionGadgetsBundle;import com.siyeh.ig.BaseInspection;
import com.intellij.psi.util.InheritanceUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
public class NewExceptionWithoutArgumentsInspection extends BaseInspection {
@SuppressWarnings("PublicField")
public boolean ignoreWithoutParameters = false;
@Nls
@NotNull
@Override
@@ -36,12 +44,18 @@ public class NewExceptionWithoutArgumentsInspection extends BaseInspection {
return InspectionGadgetsBundle.message("new.exception.without.arguments.problem.descriptor");
}
@Override
public JComponent createOptionsPanel() {
return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("new.exception.without.arguments.ignore.option"), this,
"ignoreWithoutParameters");
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new NewExceptionWithoutArgumentsVisitor();
}
private static class NewExceptionWithoutArgumentsVisitor extends BaseInspectionVisitor {
private class NewExceptionWithoutArgumentsVisitor extends BaseInspectionVisitor {
@Override
public void visitNewExpression(PsiNewExpression expression) {
@@ -63,16 +77,29 @@ public class NewExceptionWithoutArgumentsInspection extends BaseInspection {
return;
}
final PsiClass aClass = (PsiClass)target;
final GlobalSearchScope resolveScope = expression.getResolveScope();
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(expression.getProject());
final PsiClass exceptionClass = psiFacade.findClass(CommonClassNames.JAVA_LANG_EXCEPTION, resolveScope);
if (exceptionClass == null) {
if (!InheritanceUtil.isInheritor(aClass, CommonClassNames.JAVA_LANG_EXCEPTION)) {
return;
}
if (!aClass.isInheritor(exceptionClass, true)) {
return;
if (ignoreWithoutParameters) {
if (!hasAccessibleConstructorWithParameters(aClass, expression)) return;
}
registerNewExpressionError(expression);
}
private boolean hasAccessibleConstructorWithParameters(PsiClass aClass, PsiElement context) {
final PsiMethod[] constructors = aClass.getConstructors();
for (PsiMethod constructor : constructors) {
final PsiParameterList parameterList = constructor.getParameterList();
final int count = parameterList.getParametersCount();
if (count <= 0) {
continue;
}
final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(context.getProject()).getResolveHelper();
if (resolveHelper.isAccessible(constructor, context, aClass)) {
return true;
}
}
return false;
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2012 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.
@@ -16,7 +16,7 @@
package com.siyeh.ig.inheritance;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment;
@@ -34,8 +34,12 @@ import java.util.Set;
public class AbstractMethodOverridesAbstractMethodInspection extends BaseInspection {
@SuppressWarnings("PublicField")
public boolean ignoreJavaDoc = false;
@SuppressWarnings("PublicField")
public boolean ignoreAnnotations = false;
@Override
@NotNull
public String getDisplayName() {
@@ -55,8 +59,12 @@ public class AbstractMethodOverridesAbstractMethodInspection extends BaseInspect
@Override
public JComponent createOptionsPanel() {
return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message(
"abstract.method.overrides.abstract.method.ignore.different.javadoc.option"), this, "ignoreJavaDoc");
final MultipleCheckboxOptionsPanel panel = new MultipleCheckboxOptionsPanel(this);
panel.addCheckbox(InspectionGadgetsBundle.message(
"abstract.method.overrides.abstract.method.ignore.different.javadoc.option"), "ignoreJavaDoc");
panel.addCheckbox(InspectionGadgetsBundle.message(
"abstract.method.overrides.abstract.method.ignore.different.annotations.option"), "ignoreAnnotations");
return panel;
}
private static class AbstractMethodOverridesAbstractMethodFix extends InspectionGadgetsFix {
@@ -83,7 +91,6 @@ public class AbstractMethodOverridesAbstractMethodInspection extends BaseInspect
private class AbstractMethodOverridesAbstractMethodVisitor extends BaseInspectionVisitor {
@Override
public void visitMethod(@NotNull PsiMethod method) {
//no call to super, so we don't drill into anonymous classes
@@ -105,18 +112,61 @@ public class AbstractMethodOverridesAbstractMethodInspection extends BaseInspect
if (!isAbstract(superMethod)) {
continue;
}
if (!methodsHaveSameReturnTypes(method, superMethod) ||
!haveSameExceptionSignatures(method, superMethod)) {
if (!methodsHaveSameReturnTypes(method, superMethod) || !haveSameExceptionSignatures(method, superMethod)) {
continue;
}
if (ignoreJavaDoc && !haveSameJavaDoc(method, superMethod)) {
return;
}
if (ignoreAnnotations && !methodsHaveSameAnnotations(method, superMethod)) {
return;
}
registerMethodError(method);
return;
}
}
private boolean methodsHaveSameAnnotations(PsiMethod method, PsiMethod superMethod) {
if (!haveSameAnnotations(method, superMethod)) {
return false;
}
final PsiParameterList superParameterList = superMethod.getParameterList();
final PsiParameter[] superParameters = superParameterList.getParameters();
final PsiParameterList parameterList = method.getParameterList();
final PsiParameter[] parameters = parameterList.getParameters();
for (int i = 0, length = superParameters.length; i < length; i++) {
final PsiParameter superParameter = superParameters[i];
final PsiParameter parameter = parameters[i];
if (!haveSameAnnotations(parameter, superParameter)) {
return false;
}
}
return true;
}
private boolean haveSameAnnotations(PsiModifierListOwner owner1, PsiModifierListOwner owner2) {
final PsiModifierList modifierList = owner1.getModifierList();
final PsiModifierList superModifierList = owner2.getModifierList();
if (superModifierList == null) {
return modifierList == null;
} else if (modifierList == null) {
return false;
}
final PsiAnnotation[] superAnnotations = superModifierList.getAnnotations();
final PsiAnnotation[] annotations = modifierList.getAnnotations();
final Set<PsiAnnotation> annotationsSet = new HashSet<PsiAnnotation>(Arrays.asList(superAnnotations));
for (PsiAnnotation annotation : annotations) {
final String qualifiedName = annotation.getQualifiedName();
if ("java.lang.Override".equals(qualifiedName)) {
continue;
}
if (!annotationsSet.contains(annotation)) {
return false;
}
}
return true;
}
private boolean haveSameJavaDoc(PsiMethod method, PsiMethod superMethod) {
final PsiDocComment superDocComment = superMethod.getDocComment();
final PsiDocComment docComment = method.getDocComment();
@@ -1,9 +1,13 @@
<html>
<body>
This inspection reports abstract methods which override abstract methods. Methods with
This inspection reports <b>abstract</b> methods which override <b>abstract</b> methods. Methods with
different return types or exception declarations than the method they override are not
reported by this inspection.
<p>
Use the first checkbox to ignore any abstract methods that have a different JavaDoc comment than their super method.
<p>
Use the second checkbox to ignore any abstract methods that have one or more annotations that are not present on their super method.
<p>
<small>Powered by InspectionGadgets</small>
</body>
</html>
@@ -3,7 +3,7 @@
This inspection reports any checks for oddness of the form:
<code><pre>x % 2 == 1</pre></code>
Such checks will fail for negative odd values, which is probably not the behaviour intended. Consider using:
<code><pre>x % 2 != 0</pre></code> or: <code><pre>x & 1 == 1</pre></code> instead.
<code><pre>x % 2 != 0</pre></code> or: <code><pre>(x & 1) == 1</pre></code> instead.
<p>
<small>Powered by InspectionGadgets</small>
</body>
@@ -1,7 +1,9 @@
<html>
<body>
This inspection reports construction of exceptions without arguments. When an exception is constructed without arguments it contains no
information about the fault that happened, which makes debugging needlessly hard.
This inspection reports exception instance creation without any arguments specified. When an exception is constructed
without arguments it contains no information about the fault that happened, which makes debugging needlessly hard.
<p>
Use the checkbox below to ignore instance creation of exception classes which have no constructors that take arguments.
<p>
<small>New in 11, Powered by InspectionGadgets</small>
</body>
@@ -1,11 +0,0 @@
package com.siyeh.igtest.classlayout;
public abstract class AbstractMethodOverridesAbstractMethodInspection {
public abstract Object foo() throws Exception;
}
abstract class Child extends AbstractMethodOverridesAbstractMethodInspection
{
public abstract Object foo() ;
}
@@ -0,0 +1,16 @@
package com.siyeh.igtest.errorhandling.new_exception_without_arguments;
class NewExceptionWithoutArguments {
void foo() {
throw new RuntimeException();
}
void bar() {
throw new MyException();
}
}
class MyException extends RuntimeException {
}
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
<problem>
<file>NewExceptionWithoutArguments.java</file>
<line>6</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Exception constructor called without arguments</problem_class>
<description>&lt;code&gt;new RuntimeException()&lt;/code&gt; without arguments #loc</description>
</problem>
</problems>
@@ -0,0 +1,31 @@
package com.siyeh.igtest.inheritance.abstract_method_overrides_abstract_method;
import org.jetbrains.annotations.Nullable;
public abstract class AbstractMethodOverridesAbstractMethod {
public abstract Object foo() throws Exception;
abstract void one(String s);
abstract void two();
public abstract void three();
}
abstract class Child extends AbstractMethodOverridesAbstractMethod
{
public abstract String foo() ;
abstract void one(@Nullable String s);
/**
* some documentation
*/
abstract void two();
public abstract void three();
}
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
<problem>
<file>AbstractMethodOverridesAbstractMethod.java</file>
<line>30</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Abstract method overrides abstract method</problem_class>
<description>Abstract method &lt;code&gt;three()&lt;/code&gt; overrides abstract method #loc</description>
</problem>
</problems>
@@ -0,0 +1,13 @@
package com.siyeh.ig.errorhandling;
import com.siyeh.ig.IGInspectionTestCase;
public class NewExceptionWithoutArgumentsInspectionTest extends IGInspectionTestCase {
public void test() throws Exception {
final NewExceptionWithoutArgumentsInspection tool = new NewExceptionWithoutArgumentsInspection();
tool.ignoreWithoutParameters = true;
doTest("com/siyeh/igtest/errorhandling/new_exception_without_arguments", tool);
}
}
@@ -0,0 +1,13 @@
package com.siyeh.ig.inheritance;
import com.siyeh.ig.IGInspectionTestCase;
public class AbstractMethodOverridesAbstractMethodInspectionTest extends IGInspectionTestCase {
public void test() throws Exception {
final AbstractMethodOverridesAbstractMethodInspection tool = new AbstractMethodOverridesAbstractMethodInspection();
tool.ignoreAnnotations = true;
tool.ignoreJavaDoc = true;
doTest("com/siyeh/igtest/inheritance/abstract_method_overrides_abstract_method", tool);
}
}