Merge commit 'origin/master'

This commit is contained in:
Eugene Kudelevsky
2011-04-06 15:11:56 +04:00
149 changed files with 1874 additions and 622 deletions
@@ -151,6 +151,11 @@ public class ArtifactAntGenerationContextImpl implements ArtifactAntGenerationCo
return BuildProperties.getOutputPathProperty(moduleName);
}
@Override
public String getModuleTestOutputPath(@NonNls String moduleName) {
return BuildProperties.getOutputPathForTestsProperty(moduleName);
}
public List<Generator> getBeforeBuildGenerators() {
return myBeforeBuildGenerators;
}
@@ -15,9 +15,7 @@
*/
package com.intellij.packaging.impl.artifacts;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootModel;
import com.intellij.openapi.util.ModificationTracker;
import com.intellij.openapi.util.MultiValuesMap;
import com.intellij.openapi.vfs.VirtualFile;
@@ -85,12 +83,8 @@ public class ArtifactBySourceFileFinderImpl extends ArtifactBySourceFileFinder {
}
}
else if (element instanceof ModuleOutputPackagingElement) {
final Module module = ((ModuleOutputPackagingElement)element).findModule(context);
if (module != null) {
final ModuleRootModel rootModel = context.getModulesProvider().getRootModel(module);
for (VirtualFile sourceRoot : rootModel.getSourceRoots(false)) {
for (VirtualFile sourceRoot : ((ModuleOutputPackagingElement)element).getSourceRoots(context)) {
result.put(sourceRoot, artifact);
}
}
}
return true;
@@ -19,7 +19,6 @@ import com.intellij.compiler.CompilerConfiguration;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.CompilerProjectExtension;
import com.intellij.openapi.roots.ModuleRootModel;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Trinity;
@@ -360,13 +359,9 @@ public class ArtifactUtil {
@Nullable
private static String getRelativePathInSources(@NotNull VirtualFile file, final @NotNull ModuleOutputPackagingElement moduleElement,
@NotNull PackagingElementResolvingContext context) {
final Module module = moduleElement.findModule(context);
if (module != null) {
final ModuleRootModel rootModel = context.getModulesProvider().getRootModel(module);
for (VirtualFile sourceRoot : rootModel.getSourceRoots(false)) {
if (VfsUtil.isAncestor(sourceRoot, file, true)) {
return VfsUtil.getRelativePath(file, sourceRoot, '/');
}
for (VirtualFile sourceRoot : moduleElement.getSourceRoots(context)) {
if (VfsUtil.isAncestor(sourceRoot, file, true)) {
return VfsUtil.getRelativePath(file, sourceRoot, '/');
}
}
return null;
@@ -420,15 +415,11 @@ public class ArtifactUtil {
}
}
else if (element instanceof ModuleOutputPackagingElement) {
final Module module = ((ModuleOutputPackagingElement)element).findModule(context);
if (module != null) {
final CompilerConfiguration compilerConfiguration = CompilerConfiguration.getInstance(context.getProject());
final ModuleRootModel rootModel = context.getModulesProvider().getRootModel(module);
for (VirtualFile sourceRoot : rootModel.getSourceRoots(false)) {
final VirtualFile sourceFile = sourceRoot.findFileByRelativePath(path);
if (sourceFile != null && compilerConfiguration.isResourceFile(sourceFile)) {
result.add(sourceFile);
}
final CompilerConfiguration compilerConfiguration = CompilerConfiguration.getInstance(context.getProject());
for (VirtualFile sourceRoot : ((ModuleOutputPackagingElement)element).getSourceRoots(context)) {
final VirtualFile sourceFile = sourceRoot.findFileByRelativePath(path);
if (sourceFile != null && compilerConfiguration.isResourceFile(sourceFile)) {
result.add(sourceFile);
}
}
}
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.packaging.impl.artifacts.JarArtifactFromModulesDialog">
<grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="6" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="7" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
<xy x="20" y="20" width="521" height="400"/>
</constraints>
<properties/>
<border type="none"/>
@@ -18,7 +18,7 @@
</component>
<vspacer id="8cb38">
<constraints>
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
<grid row="6" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="535a8" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myMainClassField">
@@ -90,6 +90,14 @@
</component>
</children>
</grid>
<component id="d5a56" class="javax.swing.JCheckBox" binding="myIncludeTestsCheckBox">
<constraints>
<grid row="5" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;Include tests"/>
</properties>
</component>
</children>
</grid>
<buttonGroups>
@@ -15,6 +15,7 @@
*/
package com.intellij.packaging.impl.artifacts;
import com.intellij.ide.ui.ListCellRendererWrapper;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ui.configuration.ModulesAlphaComparator;
@@ -30,7 +31,6 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
@@ -47,6 +47,7 @@ public class JarArtifactFromModulesDialog extends DialogWrapper {
private JLabel myManifestDirLabel;
private JRadioButton myExtractJarsRadioButton;
private JRadioButton myCopyJarsRadioButton;
private JCheckBox myIncludeTestsCheckBox;
private PackagingElementResolvingContext myContext;
public JarArtifactFromModulesDialog(PackagingElementResolvingContext context) {
@@ -84,7 +85,7 @@ public class JarArtifactFromModulesDialog extends DialogWrapper {
for (Module module : modules) {
myModuleComboBox.addItem(module);
}
myModuleComboBox.setRenderer(new ModuleListRenderer());
myModuleComboBox.setRenderer(new ModuleListRenderer(myModuleComboBox));
init();
}
@@ -122,6 +123,10 @@ public class JarArtifactFromModulesDialog extends DialogWrapper {
return myExtractJarsRadioButton.isSelected();
}
public boolean isIncludeTests() {
return myIncludeTestsCheckBox.isSelected();
}
public String getMainClassName() {
return myMainClassField.getText();
}
@@ -136,20 +141,21 @@ public class JarArtifactFromModulesDialog extends DialogWrapper {
return myMainPanel;
}
private static class ModuleListRenderer extends DefaultListCellRenderer {
private static class ModuleListRenderer extends ListCellRendererWrapper<Module> {
public ModuleListRenderer(JComboBox comboBox) {
super(comboBox);
}
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
final Component component = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof Module) {
final Module module = (Module)value;
setIcon(module.getModuleType().getNodeIcon(false));
setText(module.getName());
public void customize(JList list, Module value, int index, boolean selected, boolean hasFocus) {
if (value != null) {
setIcon(value.getModuleType().getNodeIcon(false));
setText(value.getName());
}
else {
setText("<All Modules>");
setIcon(null);
}
return component;
}
}
}
@@ -59,12 +59,14 @@ public class JarFromModulesTemplate extends ArtifactTemplate {
}
return doCreateArtifact(dialog.getSelectedModules(), dialog.getMainClassName(), dialog.getDirectoryForManifest(),
dialog.isExtractLibrariesToJar());
dialog.isExtractLibrariesToJar(), dialog.isIncludeTests());
}
@Nullable
public NewArtifactConfiguration doCreateArtifact(final Module[] modules, final String mainClassName,
final String directoryForManifest, final boolean extractLibrariesToJar) {
final String directoryForManifest,
final boolean extractLibrariesToJar,
final boolean includeTests) {
VirtualFile manifestFile = null;
final Project project = myContext.getProject();
if (mainClassName != null && !mainClassName.isEmpty() || !extractLibrariesToJar) {
@@ -92,14 +94,21 @@ public class JarFromModulesTemplate extends ArtifactTemplate {
final PackagingElementFactory factory = PackagingElementFactory.getInstance();
final CompositePackagingElement<?> archive = factory.createArchive(FileUtil.sanitizeFileName(name) + ".jar");
final OrderEnumerator orderEnumerator = ProjectRootManager.getInstance(project).orderEntries(Arrays.asList(modules));
OrderEnumerator orderEnumerator = ProjectRootManager.getInstance(project).orderEntries(Arrays.asList(modules));
final Set<Library> libraries = new THashSet<Library>();
orderEnumerator.using(myContext.getModulesProvider()).withoutSdk().productionOnly().runtimeOnly().recursively().forEach(new Processor<OrderEntry>() {
if (!includeTests) {
orderEnumerator = orderEnumerator.productionOnly();
}
orderEnumerator.using(myContext.getModulesProvider()).withoutSdk().runtimeOnly().recursively().forEach(new Processor<OrderEntry>() {
@Override
public boolean process(OrderEntry orderEntry) {
if (orderEntry instanceof ModuleSourceOrderEntry) {
archive.addOrFindChild(factory.createModuleOutput(orderEntry.getOwnerModule()));
Module module = orderEntry.getOwnerModule();
archive.addOrFindChild(factory.createModuleOutput(module));
if (includeTests) {
archive.addOrFindChild(factory.createTestModuleOutput(module));
}
}
else if (orderEntry instanceof LibraryOrderEntry) {
ContainerUtil.addIfNotNull(((LibraryOrderEntry)orderEntry).getLibrary(), libraries);
@@ -26,7 +26,7 @@ import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.artifacts.ArtifactManager;
import com.intellij.packaging.elements.PackagingElementResolvingContext;
import com.intellij.packaging.impl.artifacts.ArtifactUtil;
import com.intellij.packaging.impl.elements.ModuleOutputElementType;
import com.intellij.packaging.impl.elements.ProductionModuleOutputElementType;
import com.intellij.packaging.impl.elements.ModuleOutputPackagingElement;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
@@ -94,7 +94,7 @@ public class ArtifactCompileScope {
private static boolean containsModuleOutput(Artifact artifact, final Set<Module> modules, ArtifactManager artifactManager) {
final PackagingElementResolvingContext context = artifactManager.getResolvingContext();
return !ArtifactUtil.processPackagingElements(artifact, ModuleOutputElementType.MODULE_OUTPUT_ELEMENT_TYPE,
return !ArtifactUtil.processPackagingElements(artifact, ProductionModuleOutputElementType.ELEMENT_TYPE,
new Processor<ModuleOutputPackagingElement>() {
public boolean process(ModuleOutputPackagingElement moduleOutputPackagingElement) {
final Module module = moduleOutputPackagingElement.findModule(context);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,12 +15,11 @@
*/
package com.intellij.packaging.impl.elements;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModulePointer;
import com.intellij.openapi.module.ModulePointerManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.util.IconLoader;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.elements.CompositePackagingElement;
import com.intellij.packaging.elements.PackagingElement;
@@ -28,49 +27,37 @@ import com.intellij.packaging.elements.PackagingElementType;
import com.intellij.packaging.ui.ArtifactEditorContext;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author nik
*/
public class ModuleOutputElementType extends PackagingElementType<ModuleOutputPackagingElementImpl> {
public static final ModuleOutputElementType MODULE_OUTPUT_ELEMENT_TYPE = new ModuleOutputElementType();
ModuleOutputElementType() {
super("module-output", CompilerBundle.message("element.type.name.module.output"));
}
@Override
public Icon getCreateElementIcon() {
return IconLoader.getIcon("/nodes/ModuleOpen.png");
* @author nik
*/
public abstract class ModuleOutputElementTypeBase<E extends ModuleOutputPackagingElementBase> extends PackagingElementType<E> {
public ModuleOutputElementTypeBase(String id, String presentableName) {
super(id, presentableName);
}
@Override
public boolean canCreate(@NotNull ArtifactEditorContext context, @NotNull Artifact artifact) {
return context.getModulesProvider().getModules().length > 0;
return !getSuitableModules(context).isEmpty();
}
@NotNull
public List<? extends PackagingElement<?>> chooseAndCreate(@NotNull ArtifactEditorContext context, @NotNull Artifact artifact,
@NotNull CompositePackagingElement<?> parent) {
List<Module> modules = chooseModules(context);
List<Module> suitableModules = getSuitableModules(context);
List<Module> selected = context.chooseModules(suitableModules, ProjectBundle.message("dialog.title.packaging.choose.module"));
final List<PackagingElement<?>> elements = new ArrayList<PackagingElement<?>>();
final ModulePointerManager pointerManager = ModulePointerManager.getInstance(context.getProject());
for (Module module : modules) {
elements.add(new ModuleOutputPackagingElementImpl(context.getProject(), pointerManager.create(module)));
for (Module module : selected) {
elements.add(createElement(context.getProject(), pointerManager.create(module)));
}
return elements;
}
public static List<Module> chooseModules(ArtifactEditorContext context) {
return context.chooseModules(Arrays.asList(context.getModulesProvider().getModules()), ProjectBundle.message("dialog.title.packaging.choose.module"));
}
protected abstract ModuleOutputPackagingElementBase createElement(@NotNull Project project, @NotNull ModulePointer pointer);
@NotNull
public ModuleOutputPackagingElementImpl createEmpty(@NotNull Project project) {
return new ModuleOutputPackagingElementImpl(project);
}
protected abstract List<Module> getSuitableModules(ArtifactEditorContext context);
}
@@ -16,9 +16,13 @@
package com.intellij.packaging.impl.elements;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.elements.PackagingElementResolvingContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
/**
* @author nik
*/
@@ -28,4 +32,7 @@ public interface ModuleOutputPackagingElement {
@Nullable
Module findModule(PackagingElementResolvingContext context);
@NotNull
Collection<VirtualFile> getSourceRoots(PackagingElementResolvingContext context);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 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.
@@ -27,10 +27,6 @@ import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.artifacts.ArtifactType;
import com.intellij.packaging.elements.*;
import com.intellij.packaging.impl.ui.DelegatedPackagingElementPresentation;
import com.intellij.packaging.impl.ui.ModuleElementPresentation;
import com.intellij.packaging.ui.ArtifactEditorContext;
import com.intellij.packaging.ui.PackagingElementPresentation;
import com.intellij.util.ArrayUtil;
import com.intellij.util.xmlb.annotations.Attribute;
import org.jetbrains.annotations.NonNls;
@@ -43,25 +39,20 @@ import java.util.List;
/**
* @author nik
*/
public class ModuleOutputPackagingElementImpl extends PackagingElement<ModuleOutputPackagingElementImpl.ModuleOutputPackagingElementState>
implements ModuleOutputPackagingElement {
public abstract class ModuleOutputPackagingElementBase extends PackagingElement<ModuleOutputPackagingElementBase.ModuleOutputPackagingElementState> implements ModuleOutputPackagingElement {
@NonNls public static final String MODULE_NAME_ATTRIBUTE = "name";
private ModulePointer myModulePointer;
private final Project myProject;
protected ModulePointer myModulePointer;
protected final Project myProject;
public ModuleOutputPackagingElementImpl(@NotNull Project project) {
super(ModuleOutputElementType.MODULE_OUTPUT_ELEMENT_TYPE);
myProject = project;
}
public ModuleOutputPackagingElementImpl(@NotNull Project project, @NotNull ModulePointer modulePointer) {
super(ModuleOutputElementType.MODULE_OUTPUT_ELEMENT_TYPE);
public ModuleOutputPackagingElementBase(PackagingElementType type, Project project, ModulePointer modulePointer) {
super(type);
myProject = project;
myModulePointer = modulePointer;
}
public PackagingElementPresentation createPresentation(@NotNull ArtifactEditorContext context) {
return new DelegatedPackagingElementPresentation(new ModuleElementPresentation(myModulePointer, context));
public ModuleOutputPackagingElementBase(PackagingElementType type, Project project) {
super(type);
myProject = project;
}
@Override
@@ -69,12 +60,14 @@ public class ModuleOutputPackagingElementImpl extends PackagingElement<ModuleOut
@NotNull ArtifactAntGenerationContext generationContext,
@NotNull ArtifactType artifactType) {
if (myModulePointer != null) {
final String moduleOutput = BuildProperties.propertyRef(generationContext.getModuleOutputPath(myModulePointer.getModuleName()));
final String moduleOutput = BuildProperties.propertyRef(getModuleOutputAntProperty(generationContext));
return Collections.singletonList(creator.createDirectoryContentCopyInstruction(moduleOutput));
}
return Collections.emptyList();
}
protected abstract String getModuleOutputAntProperty(ArtifactAntGenerationContext generationContext);
@Override
public void computeIncrementalCompilerInstructions(@NotNull IncrementalCompilerInstructionCreator creator,
@NotNull PackagingElementResolvingContext resolvingContext,
@@ -83,7 +76,7 @@ public class ModuleOutputPackagingElementImpl extends PackagingElement<ModuleOut
if (module != null) {
final CompilerModuleExtension extension = CompilerModuleExtension.getInstance(module);
if (extension != null) {
final VirtualFile output = extension.getCompilerOutputPath();
final VirtualFile output = getModuleOutputPath(extension);
if (output != null) {
creator.addDirectoryCopyInstructions(output, null);
}
@@ -91,6 +84,9 @@ public class ModuleOutputPackagingElementImpl extends PackagingElement<ModuleOut
}
}
@Nullable
protected abstract VirtualFile getModuleOutputPath(CompilerModuleExtension extension);
@NotNull
@Override
public PackagingElementOutputKind getFilesKind(PackagingElementResolvingContext context) {
@@ -99,8 +95,8 @@ public class ModuleOutputPackagingElementImpl extends PackagingElement<ModuleOut
@Override
public boolean isEqualTo(@NotNull PackagingElement<?> element) {
return element instanceof ModuleOutputPackagingElementImpl && myModulePointer != null
&& myModulePointer.equals(((ModuleOutputPackagingElementImpl)element).myModulePointer);
return element.getClass() == getClass() && myModulePointer != null
&& myModulePointer.equals(((ModuleOutputPackagingElementBase)element).myModulePointer);
}
public ModuleOutputPackagingElementState getState() {
@@ -116,11 +112,6 @@ public class ModuleOutputPackagingElementImpl extends PackagingElement<ModuleOut
myModulePointer = moduleName != null ? ModulePointerManager.getInstance(myProject).create(moduleName) : null;
}
@NonNls @Override
public String toString() {
return "module:" + getModuleName();
}
@Override
@Nullable
public String getModuleName() {
@@ -58,7 +58,7 @@ public class PackagingElementFactoryImpl extends PackagingElementFactory {
public static final PackagingElementType<ArtifactRootElement<?>> ARTIFACT_ROOT_ELEMENT_TYPE = new ArtifactRootElementType();
private static final PackagingElementType[] STANDARD_TYPES = {
DIRECTORY_ELEMENT_TYPE, ARCHIVE_ELEMENT_TYPE,
LibraryElementType.LIBRARY_ELEMENT_TYPE, ModuleOutputElementType.MODULE_OUTPUT_ELEMENT_TYPE,
LibraryElementType.LIBRARY_ELEMENT_TYPE, ProductionModuleOutputElementType.ELEMENT_TYPE, TestModuleOutputElementType.ELEMENT_TYPE,
ArtifactElementType.ARTIFACT_ELEMENT_TYPE, FILE_COPY_ELEMENT_TYPE, DIRECTORY_COPY_ELEMENT_TYPE, EXTRACTED_DIRECTORY_ELEMENT_TYPE
};
@@ -181,14 +181,21 @@ public class PackagingElementFactoryImpl extends PackagingElementFactory {
@NotNull
public PackagingElement<?> createModuleOutput(@NotNull String moduleName, @NotNull Project project) {
final ModulePointer pointer = ModulePointerManager.getInstance(project).create(moduleName);
return new ModuleOutputPackagingElementImpl(project, pointer);
return new ProductionModuleOutputPackagingElement(project, pointer);
}
@NotNull
@Override
public PackagingElement<?> createModuleOutput(@NotNull Module module) {
final ModulePointer modulePointer = ModulePointerManager.getInstance(module.getProject()).create(module);
return new ModuleOutputPackagingElementImpl(module.getProject(), modulePointer);
return new ProductionModuleOutputPackagingElement(module.getProject(), modulePointer);
}
@NotNull
@Override
public PackagingElement<?> createTestModuleOutput(@NotNull Module module) {
ModulePointer pointer = ModulePointerManager.getInstance(module.getProject()).create(module);
return new TestModuleOutputPackagingElement(module.getProject(), pointer);
}
@NotNull
@@ -0,0 +1,65 @@
/*
* Copyright 2000-2009 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.packaging.impl.elements;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModulePointer;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.openapi.util.IconLoader;
import com.intellij.packaging.ui.ArtifactEditorContext;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
/**
* @author nik
*/
public class ProductionModuleOutputElementType extends ModuleOutputElementTypeBase<ProductionModuleOutputPackagingElement> {
public static final ProductionModuleOutputElementType ELEMENT_TYPE = new ProductionModuleOutputElementType();
ProductionModuleOutputElementType() {
super("module-output", CompilerBundle.message("element.type.name.module.output"));
}
@NotNull
public ProductionModuleOutputPackagingElement createEmpty(@NotNull Project project) {
return new ProductionModuleOutputPackagingElement(project);
}
protected ModuleOutputPackagingElementBase createElement(@NotNull Project project, @NotNull ModulePointer pointer) {
return new ProductionModuleOutputPackagingElement(project, pointer);
}
@Override
public Icon getCreateElementIcon() {
return IconLoader.getIcon("/nodes/ModuleOpen.png");
}
protected List<Module> getSuitableModules(ArtifactEditorContext context) {
ArrayList<Module> modules = new ArrayList<Module>();
ModulesProvider modulesProvider = context.getModulesProvider();
for (Module module : modulesProvider.getModules()) {
if (modulesProvider.getRootModel(module).getSourceRootUrls(false).length > 0) {
modules.add(module);
}
}
return modules;
}
}
@@ -0,0 +1,75 @@
/*
* Copyright 2000-2009 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.packaging.impl.elements;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModulePointer;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.CompilerModuleExtension;
import com.intellij.openapi.roots.ModuleRootModel;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.elements.ArtifactAntGenerationContext;
import com.intellij.packaging.elements.PackagingElementResolvingContext;
import com.intellij.packaging.impl.ui.DelegatedPackagingElementPresentation;
import com.intellij.packaging.impl.ui.ModuleElementPresentation;
import com.intellij.packaging.ui.ArtifactEditorContext;
import com.intellij.packaging.ui.PackagingElementPresentation;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
/**
* @author nik
*/
public class ProductionModuleOutputPackagingElement extends ModuleOutputPackagingElementBase {
public ProductionModuleOutputPackagingElement(@NotNull Project project) {
super(ProductionModuleOutputElementType.ELEMENT_TYPE, project);
}
public ProductionModuleOutputPackagingElement(@NotNull Project project, @NotNull ModulePointer modulePointer) {
super(ProductionModuleOutputElementType.ELEMENT_TYPE, project, modulePointer);
}
@NonNls @Override
public String toString() {
return "module:" + getModuleName();
}
protected String getModuleOutputAntProperty(ArtifactAntGenerationContext generationContext) {
return generationContext.getModuleOutputPath(myModulePointer.getModuleName());
}
protected VirtualFile getModuleOutputPath(CompilerModuleExtension extension) {
return extension.getCompilerOutputPath();
}
@NotNull
@Override
public Collection<VirtualFile> getSourceRoots(PackagingElementResolvingContext context) {
Module module = findModule(context);
if (module == null) return Collections.emptyList();
ModuleRootModel rootModel = context.getModulesProvider().getRootModel(module);
return Arrays.asList(rootModel.getSourceRoots(false));
}
public PackagingElementPresentation createPresentation(@NotNull ArtifactEditorContext context) {
return new DelegatedPackagingElementPresentation(new ModuleElementPresentation(myModulePointer, context, false));
}
}
@@ -0,0 +1,78 @@
/*
* Copyright 2000-2011 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.packaging.impl.elements;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModulePointer;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModuleRootModel;
import com.intellij.openapi.roots.SourceFolder;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.packaging.ui.ArtifactEditorContext;
import com.intellij.util.Icons;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
/**
* @author nik
*/
public class TestModuleOutputElementType extends ModuleOutputElementTypeBase<TestModuleOutputPackagingElement> {
public static final TestModuleOutputElementType ELEMENT_TYPE = new TestModuleOutputElementType();
public TestModuleOutputElementType() {
super("module-test-output", CompilerBundle.message("element.type.name.module.test.output"));
}
@NotNull
@Override
public TestModuleOutputPackagingElement createEmpty(@NotNull Project project) {
return new TestModuleOutputPackagingElement(project);
}
protected ModuleOutputPackagingElementBase createElement(@NotNull Project project, @NotNull ModulePointer pointer) {
return new TestModuleOutputPackagingElement(project, pointer);
}
@Override
public Icon getCreateElementIcon() {
return Icons.TEST_SOURCE_FOLDER;
}
protected List<Module> getSuitableModules(ArtifactEditorContext context) {
ModulesProvider modulesProvider = context.getModulesProvider();
ArrayList<Module> modules = new ArrayList<Module>();
for (Module module : modulesProvider.getModules()) {
if (hasTestSourceRoots(modulesProvider.getRootModel(module))) {
modules.add(module);
}
}
return modules;
}
private static boolean hasTestSourceRoots(final ModuleRootModel rootModel) {
for (ContentEntry entry : rootModel.getContentEntries()) {
for (SourceFolder folder : entry.getSourceFolders()) {
if (folder.isTestSource()) return true;
}
}
return false;
}
}
@@ -0,0 +1,86 @@
/*
* Copyright 2000-2011 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.packaging.impl.elements;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModulePointer;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.CompilerModuleExtension;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModuleRootModel;
import com.intellij.openapi.roots.SourceFolder;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.elements.ArtifactAntGenerationContext;
import com.intellij.packaging.elements.PackagingElementResolvingContext;
import com.intellij.packaging.impl.ui.DelegatedPackagingElementPresentation;
import com.intellij.packaging.impl.ui.ModuleElementPresentation;
import com.intellij.packaging.ui.ArtifactEditorContext;
import com.intellij.packaging.ui.PackagingElementPresentation;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* @author nik
*/
public class TestModuleOutputPackagingElement extends ModuleOutputPackagingElementBase {
public TestModuleOutputPackagingElement(Project project) {
super(TestModuleOutputElementType.ELEMENT_TYPE, project);
}
public TestModuleOutputPackagingElement(Project project, ModulePointer modulePointer) {
super(TestModuleOutputElementType.ELEMENT_TYPE, project, modulePointer);
}
@Override
public String toString() {
return "module-tests:" + getModuleName();
}
protected String getModuleOutputAntProperty(ArtifactAntGenerationContext generationContext) {
return generationContext.getModuleTestOutputPath(myModulePointer.getModuleName());
}
protected VirtualFile getModuleOutputPath(CompilerModuleExtension extension) {
return extension.getCompilerOutputPathForTests();
}
@NotNull
@Override
public Collection<VirtualFile> getSourceRoots(PackagingElementResolvingContext context) {
Module module = findModule(context);
if (module == null) return Collections.emptyList();
List<VirtualFile> roots = new SmartList<VirtualFile>();
ModuleRootModel rootModel = context.getModulesProvider().getRootModel(module);
for (ContentEntry entry : rootModel.getContentEntries()) {
for (SourceFolder folder : entry.getSourceFolders()) {
if (folder.isTestSource()) {
ContainerUtil.addIfNotNull(folder.getFile(), roots);
}
}
}
return roots;
}
public PackagingElementPresentation createPresentation(@NotNull ArtifactEditorContext context) {
return new DelegatedPackagingElementPresentation(new ModuleElementPresentation(myModulePointer, context, true));
}
}
@@ -20,10 +20,11 @@ import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModulePointer;
import com.intellij.packaging.ui.ArtifactEditorContext;
import com.intellij.packaging.ui.PackagingElementWeights;
import com.intellij.packaging.ui.TreeNodePresentation;
import com.intellij.packaging.ui.ArtifactEditorContext;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.Icons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -33,10 +34,12 @@ import org.jetbrains.annotations.Nullable;
public class ModuleElementPresentation extends TreeNodePresentation {
private final ModulePointer myModulePointer;
private final ArtifactEditorContext myContext;
private final boolean myTestOutput;
public ModuleElementPresentation(@Nullable ModulePointer modulePointer, @NotNull ArtifactEditorContext context) {
public ModuleElementPresentation(@Nullable ModulePointer modulePointer, @NotNull ArtifactEditorContext context, final boolean testOutput) {
myModulePointer = modulePointer;
myContext = context;
myTestOutput = testOutput;
}
public String getPresentableName() {
@@ -68,7 +71,10 @@ public class ModuleElementPresentation extends TreeNodePresentation {
public void render(@NotNull PresentationData presentationData, SimpleTextAttributes mainAttributes, SimpleTextAttributes commentAttributes) {
final Module module = findModule();
if (module != null) {
if (myTestOutput) {
presentationData.setIcons(Icons.TEST_SOURCE_FOLDER);
}
else if (module != null) {
presentationData.setOpenIcon(module.getModuleType().getNodeIcon(true));
presentationData.setClosedIcon(module.getModuleType().getNodeIcon(false));
}
@@ -90,8 +96,9 @@ public class ModuleElementPresentation extends TreeNodePresentation {
moduleName = "<unknown>";
}
presentationData.addText(CompilerBundle.message("node.text.0.compile.output", moduleName),
module != null ? mainAttributes : SimpleTextAttributes.ERROR_ATTRIBUTES);
String text = myTestOutput ? CompilerBundle.message("node.text.0.test.compile.output", moduleName)
: CompilerBundle.message("node.text.0.compile.output", moduleName);
presentationData.addText(text, module != null ? mainAttributes : SimpleTextAttributes.ERROR_ATTRIBUTES);
}
@Override
@@ -37,6 +37,8 @@ public interface ArtifactAntGenerationContext {
String getModuleOutputPath(@NonNls String moduleName);
String getModuleTestOutputPath(@NonNls String moduleName);
String getSubstitutedPath(@NonNls String path);
String getArtifactOutputProperty(@NotNull Artifact artifact);
@@ -52,6 +52,9 @@ public abstract class PackagingElementFactory {
@NotNull
public abstract PackagingElement<?> createModuleOutput(@NotNull Module module);
@NotNull
public abstract PackagingElement<?> createTestModuleOutput(@NotNull Module module);
@NotNull
public abstract List<? extends PackagingElement<?>> createLibraryElements(@NotNull Library library);
@@ -20,7 +20,7 @@ import com.intellij.openapi.module.ModulePointer;
import com.intellij.openapi.module.ModulePointerManager;
import com.intellij.packaging.elements.PackagingElement;
import com.intellij.packaging.elements.PackagingElementOutputKind;
import com.intellij.packaging.impl.elements.ModuleOutputPackagingElementImpl;
import com.intellij.packaging.impl.elements.ProductionModuleOutputPackagingElement;
import com.intellij.packaging.impl.ui.ModuleElementPresentation;
import com.intellij.packaging.ui.*;
import org.jetbrains.annotations.NotNull;
@@ -49,7 +49,7 @@ public class ModuleOutputSourceItem extends PackagingSourceItem {
@Override
public SourceItemPresentation createPresentation(@NotNull ArtifactEditorContext context) {
final ModulePointer modulePointer = ModulePointerManager.getInstance(context.getProject()).create(myModule);
return new DelegatedSourceItemPresentation(new ModuleElementPresentation(modulePointer, context)) {
return new DelegatedSourceItemPresentation(new ModuleElementPresentation(modulePointer, context, false)) {
@Override
public int getWeight() {
return SourceItemWeights.MODULE_OUTPUT_WEIGHT;
@@ -60,7 +60,7 @@ public class ModuleOutputSourceItem extends PackagingSourceItem {
@NotNull
public List<? extends PackagingElement<?>> createElements(@NotNull ArtifactEditorContext context) {
final ModulePointer modulePointer = ModulePointerManager.getInstance(context.getProject()).create(myModule);
return Collections.singletonList(new ModuleOutputPackagingElementImpl(context.getProject(), modulePointer));
return Collections.singletonList(new ProductionModuleOutputPackagingElement(context.getProject(), modulePointer));
}
@NotNull
@@ -24,7 +24,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.impl.artifacts.ArtifactUtil;
import com.intellij.packaging.impl.elements.FileCopyPackagingElement;
import com.intellij.packaging.impl.elements.ModuleOutputElementType;
import com.intellij.packaging.impl.elements.ProductionModuleOutputElementType;
import com.intellij.packaging.impl.elements.ModuleOutputPackagingElement;
import com.intellij.packaging.impl.elements.PackagingElementFactoryImpl;
import com.intellij.packaging.ui.ArtifactEditorContext;
@@ -109,7 +109,7 @@ public class ModulesAndLibrariesSourceItemsProvider extends PackagingSourceItems
private static List<? extends Module> getNotAddedModules(@NotNull final ArtifactEditorContext context, @NotNull Artifact artifact,
final Module... allModules) {
final Set<Module> modules = new HashSet<Module>(Arrays.asList(allModules));
ArtifactUtil.processPackagingElements(artifact, ModuleOutputElementType.MODULE_OUTPUT_ELEMENT_TYPE, new Processor<ModuleOutputPackagingElement>() {
ArtifactUtil.processPackagingElements(artifact, ProductionModuleOutputElementType.ELEMENT_TYPE, new Processor<ModuleOutputPackagingElement>() {
public boolean process(ModuleOutputPackagingElement moduleOutputPackagingElement) {
modules.remove(moduleOutputPackagingElement.findModule(context));
return true;
@@ -81,7 +81,7 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
static final ElementPattern<PsiElement> AFTER_THROW_NEW = psiElement().afterLeaf(psiElement().withText(PsiKeyword.NEW).afterLeaf(PsiKeyword.THROW));
private static final OrFilter THROWABLE_TYPE_FILTER = new OrFilter(
new GeneratorFilter(AssignableGroupFilter.class, new ThrowsListGetter()),
new AssignableFromFilter(CommonClassNames.JAVA_LANG_RUNTIME_EXCEPTION));
new AssignableFromFilter(CommonClassNames.JAVA_LANG_THROWABLE));
public static final ElementPattern<PsiElement> INSIDE_EXPRESSION = or(
psiElement().withParent(PsiExpression.class).andNot(psiElement().withParent(PsiLiteralExpression.class)),
psiElement().inside(PsiClassObjectAccessExpression.class),
@@ -20,12 +20,15 @@ import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.intention.impl.TypeExpression;
import com.intellij.codeInsight.template.Template;
import com.intellij.codeInsight.template.TemplateBuilderImpl;
import com.intellij.codeInsight.template.TemplateEditingAdapter;
import com.intellij.codeInsight.template.TemplateManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
@@ -59,10 +62,10 @@ public class CreateLocalFromUsageFix extends CreateVarFromUsageFix {
return;
}
Project project = myReferenceExpression.getProject();
final Project project = myReferenceExpression.getProject();
PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
PsiFile targetFile = targetClass.getContainingFile();
final PsiFile targetFile = targetClass.getContainingFile();
PsiType[] expectedTypes = CreateFromUsageUtils.guessType(myReferenceExpression, false);
PsiType type = expectedTypes[0];
@@ -104,12 +107,25 @@ public class CreateLocalFromUsageFix extends CreateVarFromUsageFix {
builder.setEndVariableAfter(var.getNameIdentifier());
Template template = builder.buildTemplate();
Editor newEditor = positionCursor(project, targetFile, var);
final Editor newEditor = positionCursor(project, targetFile, var);
TextRange range = var.getTextRange();
newEditor.getDocument().deleteString(range.getStartOffset(), range.getEndOffset());
TemplateManager manager = TemplateManager.getInstance(project);
manager.startTemplate(newEditor, template);
startTemplate(newEditor, template, project, new TemplateEditingAdapter() {
@Override
public void templateFinished(Template template, boolean brokenOff) {
PsiDocumentManager.getInstance(project).commitDocument(newEditor.getDocument());
final int offset = newEditor.getCaretModel().getOffset();
final PsiLocalVariable localVariable = PsiTreeUtil.findElementOfClassAtOffset(targetFile, offset, PsiLocalVariable.class, false);
if (localVariable != null) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
CodeStyleManager.getInstance(project).reformat(localVariable);
}
});
}
}
});
}
protected boolean isAllowOuterTargetClass() {
@@ -532,9 +532,10 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
generateBoxingUnboxingInstructionFor(caseExpression, PsiType.INT);
if (TypeConversionUtil.isEnumType(caseExpression.getType())) {
addInstruction(new FieldReferenceInstruction(caseExpression, "switch statement expression"));
} else {
addInstruction(new PopInstruction());
}
addInstruction(new PopInstruction());
}
PsiCodeBlock body = switchStmt.getBody();
@@ -161,7 +161,8 @@ public class DataFlowRunner {
LOG.error(psiBlock.getText(), e); /* TODO[max] !!! hack (of 18186). Please fix in better times. */
return RunnerResult.ABORTED;
}
catch (EmptyStackException e) /* TODO[max] !!! hack (of 18186). Please fix in better times. */ {
catch (EmptyStackException e) {
//LOG.error(psiBlock.getText(), e); /* TODO[max] !!! hack (of 18186). Please fix in better times. */
return RunnerResult.ABORTED;
}
}
@@ -57,7 +57,7 @@ public class MethodCallInstruction extends Instruction {
public MethodCallInstruction(@NotNull PsiExpression context, MethodType methodType) {
myContext = context;
myMethodType = methodType;
myCall = context instanceof PsiCallExpression ? (PsiCallExpression)context : null;
myCall = methodType == MethodType.REGULAR_METHOD_CALL && context instanceof PsiCallExpression ? (PsiCallExpression)context : null;
final PsiExpressionList argList = myCall == null ? null : myCall.getArgumentList();
myArgs = argList != null ? argList.getExpressions() : PsiExpression.EMPTY_ARRAY;
@@ -39,6 +39,7 @@ import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.Properties;
@@ -170,7 +171,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
@NotNull
@Override
public PsiAnnotation createAnnotationFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, ANNOTATION, false), context);
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, ANNOTATION, level(context)), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
if (!(element instanceof PsiAnnotation)) {
throw new IncorrectOperationException("Incorrect annotation \"" + text + "\".");
@@ -219,7 +220,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
@NotNull
@Override
public PsiField createFieldFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, DECLARATION, false), context);
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, DECLARATION, level(context)), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
if (!(element instanceof PsiField)) {
throw new IncorrectOperationException("Incorrect field \"" + text + "\".");
@@ -230,7 +231,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
@NotNull
@Override
public PsiMethod createMethodFromText(@NotNull final String text, final PsiElement context, final LanguageLevel level) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, DECLARATION, false, level), context);
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, DECLARATION, level), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
if (!(element instanceof PsiMethod)) {
throw new IncorrectOperationException("Incorrect method \"" + text + "\" (" + element + ").");
@@ -248,7 +249,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
@NotNull
@Override
public PsiParameter createParameterFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, PARAMETER, false), context);
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, PARAMETER, level(context)), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
if (!(element instanceof PsiParameter)) {
throw new IncorrectOperationException("Incorrect parameter \"" + text + "\".");
@@ -259,7 +260,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
@NotNull
@Override
public PsiResourceVariable createResourceFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, RESOURCE, false), context);
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, RESOURCE, level(context)), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
if (!(element instanceof PsiResourceVariable)) {
throw new IncorrectOperationException("Incorrect resource \"" + text + "\".");
@@ -276,7 +277,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
@NotNull
@Override
public PsiTypeElement createTypeElementFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, TYPE, false), context);
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, TYPE, level(context)), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
if (!(element instanceof PsiTypeElement)) {
throw new IncorrectOperationException("Incorrect type \"" + text + "\".");
@@ -303,7 +304,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
final boolean mayHaveDiamonds = context instanceof PsiNewExpression &&
PsiUtil.getLanguageLevel(context).isAtLeast(LanguageLevel.JDK_1_7);
final JavaParserUtil.ParserWrapper wrapper = isStaticImport ? STATIC_IMPORT_REF : mayHaveDiamonds ? DIAMOND_REF : REFERENCE;
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, wrapper, false), context);
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, wrapper, level(context)), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
if (!(element instanceof PsiJavaCodeReferenceElement)) {
throw new IncorrectOperationException("Incorrect reference \"" + text + "\".");
@@ -314,7 +315,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
@NotNull
@Override
public PsiCodeBlock createCodeBlockFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, CODE_BLOCK, true), context);
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, CODE_BLOCK, level(context), true), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
if (!(element instanceof PsiCodeBlock)) {
throw new IncorrectOperationException("Incorrect code block \"" + text + "\".");
@@ -325,7 +326,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
@NotNull
@Override
public PsiStatement createStatementFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, STATEMENT, false), context);
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, STATEMENT, level(context)), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
if (!(element instanceof PsiStatement)) {
throw new IncorrectOperationException("Incorrect statement \"" + text + "\".");
@@ -336,7 +337,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
@NotNull
@Override
public PsiExpression createExpressionFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, EXPRESSION, false), context);
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, EXPRESSION, level(context)), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
if (!(element instanceof PsiExpression)) {
throw new IncorrectOperationException("Incorrect expression \"" + text + "\".");
@@ -353,7 +354,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
@NotNull
@Override
public PsiTypeParameter createTypeParameterFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, TYPE_PARAMETER, false), context);
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, TYPE_PARAMETER, level(context)), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
if (!(element instanceof PsiTypeParameter)) {
throw new IncorrectOperationException("Incorrect type parameter \"" + text + "\".");
@@ -382,7 +383,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
@NotNull
@Override
public PsiEnumConstant createEnumConstantFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, ENUM_CONSTANT, false), context);
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, ENUM_CONSTANT, level(context)), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
if (!(element instanceof PsiEnumConstant)) {
throw new IncorrectOperationException("Incorrect enum constant \"" + text + "\".");
@@ -396,7 +397,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
final PsiElement context) throws IncorrectOperationException {
final String text = StringUtil
.join("catch (", exceptionType.getCanonicalText(), " ", exceptionName, ") {}");
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, CATCH_SECTION, false), context);
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, CATCH_SECTION, level(context)), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
if (!(element instanceof PsiCatchSection)) {
throw new IncorrectOperationException("Incorrect catch section '" + text + "'. Parsed element: "+element);
@@ -444,4 +445,8 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
public static PsiPrimitiveType getPrimitiveType(final String text) {
return PRIMITIVE_TYPES.get(text);
}
private static LanguageLevel level(@Nullable final PsiElement context) {
return context != null ? PsiUtil.getLanguageLevel(context) : LanguageLevel.HIGHEST;
}
}
@@ -21,12 +21,14 @@ import com.intellij.lang.java.parser.JavaParserUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.CharFilter;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiElementFactoryImpl;
import com.intellij.psi.impl.source.DummyHolder;
import com.intellij.psi.impl.source.DummyHolderFactory;
import com.intellij.psi.impl.source.JavaDummyElement;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
@@ -85,7 +87,8 @@ public class ClsParsingUtil {
final String exprText = mapIndeterminate(text);
final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
final PsiJavaFile context = ((PsiElementFactoryImpl)factory).getDummyJavaFile(); // to resolve classes from java.lang
final DummyHolder holder = DummyHolderFactory.createHolder(manager, new JavaDummyElement(exprText, ANNOTATION_VALUE, false), context);
final LanguageLevel level = PsiUtil.getLanguageLevel(parent);
final DummyHolder holder = DummyHolderFactory.createHolder(manager, new JavaDummyElement(exprText, ANNOTATION_VALUE, level), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
if (!(element instanceof PsiAnnotationMemberValue)) {
LOG.error("Could not parse initializer:'" + exprText + "'");
@@ -28,22 +28,24 @@ import org.jetbrains.annotations.Nullable;
* See {@link com.intellij.psi.impl.PsiJavaParserFacadeImpl} for details.
*/
public class JavaDummyElement extends FileElement {
@NotNull private final JavaParserUtil.ParserWrapper myParser;
private final JavaParserUtil.ParserWrapper myParser;
private final LanguageLevel myLanguageLevel;
private final boolean myConsumeAll;
@NotNull private final LanguageLevel myLanguageLevel;
public JavaDummyElement(@Nullable final CharSequence text, @NotNull final JavaParserUtil.ParserWrapper parser, final boolean consumeAll) {
this(text, parser, consumeAll, LanguageLevel.HIGHEST);
public JavaDummyElement(@Nullable final CharSequence text,
@NotNull final JavaParserUtil.ParserWrapper parser,
@NotNull final LanguageLevel level) {
this(text, parser, level, false);
}
public JavaDummyElement(@Nullable final CharSequence text,
@NotNull final JavaParserUtil.ParserWrapper parser,
final boolean consumeAll,
@NotNull final LanguageLevel level) {
@NotNull final LanguageLevel level,
final boolean consumeAll) {
super(JavaElementType.DUMMY_ELEMENT, text);
myParser = parser;
myConsumeAll = consumeAll;
myLanguageLevel = level;
myConsumeAll = consumeAll;
}
@NotNull
@@ -43,7 +43,7 @@ import java.io.IOException;
public class JavaFileElementType extends ILightStubFileElementType<PsiJavaFileStub> {
public static boolean USE_NEW_STUB_BUILDER = true;
public static final int STUB_VERSION = (USE_NEW_STUB_BUILDER ? 6 : 5) + 2;
public static final int STUB_VERSION = (USE_NEW_STUB_BUILDER ? 6 : 5) + 3;
public JavaFileElementType() {
super("java.FILE", StdLanguages.JAVA);
@@ -36,6 +36,7 @@ import com.intellij.psi.impl.source.codeStyle.CodeEditUtil;
import com.intellij.psi.impl.source.parsing.ParseUtilBase;
import com.intellij.psi.templateLanguages.OuterLanguageElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.CharTable;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
@@ -76,7 +77,8 @@ public class JavaChangeUtilSupport implements TreeGenerator, TreeCopyHandler {
if (original instanceof PsiModifierList) {
final String text = original.getText();
assert text != null : "Text is null for " + original + "; " + original.getClass();
final DummyHolder holder = DummyHolderFactory.createHolder(original.getManager(), new JavaDummyElement(text, MOD_LIST, false), null);
final LanguageLevel level = PsiUtil.getLanguageLevel(original);
final DummyHolder holder = DummyHolderFactory.createHolder(original.getManager(), new JavaDummyElement(text, MOD_LIST, level), null);
final TreeElement modifierListElement = holder.getTreeElement().getFirstChildNode();
if (CodeEditUtil.isNodeGenerated(original.getNode())) modifierListElement.acceptTree(new GeneratedMarkerVisitor());
return modifierListElement;
@@ -0,0 +1,17 @@
class Foo {
boolean foo(Object o, final PairFunction<String, ElementType, Boolean> fun){
boolean result = true;
result |= fun.fun(path);
if (o instanceof String) {
o.subst<caret>
}
}
void foo(String s) {}
}
interface PairFunction<T, V, U> {
U fun(T t, V v);
}
@@ -0,0 +1,17 @@
class Foo {
boolean foo(Object o, final PairFunction<String, ElementType, Boolean> fun){
boolean result = true;
result |= fun.fun(path);
if (o instanceof String) {
((String) o).substring(<caret>)
}
}
void foo(String s) {}
}
interface PairFunction<T, V, U> {
U fun(T t, V v);
}
@@ -0,0 +1,9 @@
import sun.swing.BakedArrayList;
class Foo {
{
Object element;
if (element instanceof bar<caret>)
}
}
@@ -1,6 +1,6 @@
class A{
void foo() throws MyException{
throw new Erro<caret>
throw new Error(<caret>);
}
class MyException extends Exception{}
@@ -0,0 +1,9 @@
import pkg.Bar;
import pkg.enum.Foo;
class Test {
void m() {
Bar b = new Bar();
b.doSomething(Foo.FOO); // with language level JDK 1.4 'enum' shouldn't be a keyword (see IDEA-67556)
}
}
@@ -0,0 +1,9 @@
package pkg;
import pkg.enum.Foo;
public class Bar {
public void doSomething(Foo foo) {
System.out.println("foo=" + foo);
}
}
@@ -0,0 +1,5 @@
package pkg.enum;
public class Foo {
public static Foo FOO = new Foo();
}
@@ -0,0 +1,12 @@
// "Create Local Variable 'field'" "true"
import java.util.*;
class A {
void foo(Map<String, String> s){}
void bar() {
Map<String, String> field<caret>;
foo(field);
}
}
@@ -0,0 +1,11 @@
// "Create Local Variable 'field'" "true"
import java.util.*;
class A {
void foo(Map<String, String> s){}
void bar() {
foo(fie<caret>ld);
}
}
@@ -631,4 +631,24 @@ public interface Test {
assert !lookup
}
public void testTemplateSelection() {
myFixture.configureByText("a.java", """
class Foo {
int ITER = 2;
int itea = 2;
{
it<caret>
}
}
""")
type 'e'
assertOrderedEquals myFixture.lookupElementStrings, "itea"
type 'r'
assertOrderedEquals myFixture.lookupElementStrings, "iter", "ITER", "Iterable", "Iterator"
type ','
assert !lookup
assert myFixture.editor.document.text.contains('iter,')
}
}
@@ -217,4 +217,20 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase {
checkPreferredItems(0, "Bar9", "Bar1", "Bar2", "Bar3", "Bar4");
}
public void testSortSameNamedVariantsByProximity() {
myFixture.addClass("public class Bar {}");
for (int i = 0; i < 10; i++) {
myFixture.addClass("public class Bar" + i + " {}");
myFixture.addClass("public class Bar" + i + "Colleague {}");
}
myFixture.addClass("package bar; public class Bar {}");
final String path = getTestName(false) + ".java";
myFixture.configureByFile(getTestName(false) + ".java");
myFixture.complete(CompletionType.BASIC, 2);
assertPreferredItems(0);
List<LookupElement> items = getLookup().getItems();
assertEquals(((JavaPsiClassReferenceElement)items.get(0)).getQualifiedName(), "Bar");
assertEquals(((JavaPsiClassReferenceElement)items.get(1)).getQualifiedName(), "bar.Bar");
}
}
@@ -809,6 +809,8 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase {
public void testQualifierCastingWithUnknownAssignments() throws Throwable { doTest(); }
public void testQualifierCastingBeforeLt() throws Throwable { doTest(); }
public void testOrAssignmentDfa() throws Throwable { doTest(); }
public void testWildcardsInLookup() throws Exception {
configure()
assertNotNull(getLookup());
@@ -196,4 +196,9 @@ public class AdvHighlightingTest extends DaemonAnalyzerTestCase {
assert vFile2 != null;
assertEquals(vFile1.getParent(), vFile2.getParent());
}
public void testNotAKeywords() throws Exception {
LanguageLevelProjectExtension.getInstance(myProject).setLanguageLevel(LanguageLevel.JDK_1_4);
doTest(BASE_PATH + "/notAKeywords/Test.java", BASE_PATH + "/notAKeywords", false, false);
}
}
@@ -108,7 +108,7 @@ public abstract class PsiType implements PsiAnnotationOwner {
* @return the class instance.
*/
@NotNull
public static PsiClassType getJavaLangObject(PsiManager manager, GlobalSearchScope resolveScope) {
public static PsiClassType getJavaLangObject(@NotNull PsiManager manager, @NotNull GlobalSearchScope resolveScope) {
return JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, resolveScope);
}
@@ -102,14 +102,15 @@ public class PsiWildcardType extends PsiType {
}
}
@NotNull
public GlobalSearchScope getResolveScope() {
if (myBound != null) {
return myBound.getResolveScope();
}
else {
return GlobalSearchScope.allScope(myManager.getProject());
GlobalSearchScope scope = myBound.getResolveScope();
if (scope != null) {
return scope;
}
}
return GlobalSearchScope.allScope(myManager.getProject());
}
@NotNull
@@ -16,6 +16,8 @@
package com.intellij.openapi.module;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
@@ -23,7 +25,7 @@ public class ModuleServiceManager {
private ModuleServiceManager() {
}
public static <T> T getService(Module module, Class<T> serviceClass) {
public static <T> T getService(@NotNull Module module, @NotNull Class<T> serviceClass) {
return (T)module.getPicoContainer().getComponentInstance(serviceClass.getName());
}
}
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
/**
* @author peter
* @see com.intellij.pom.references.PomService#convertToPsi(PomTarget)
*/
public interface PomTargetPsiElement extends PsiElement {
@@ -15,11 +15,11 @@
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.completion.impl.NegatingComparable;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.proximity.PsiProximityComparator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author peter
@@ -27,13 +27,18 @@ import org.jetbrains.annotations.Nullable;
public class LookupElementProximityWeigher extends CompletionWeigher {
public Comparable weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) {
if (location == null) {
return null;
}
final Object o = item.getObject();
if (o instanceof PsiElement) {
return PsiProximityComparator.getProximity((PsiElement)o, location.getCompletionParameters().getPosition(), location.getProcessingContext());
}
return null;
}
public static class Negative extends LookupElementProximityWeigher {
@Override
public Comparable weigh(@NotNull LookupElement element, @NotNull CompletionLocation location) {
return new NegatingComparable(super.weigh(element, location));
}
}
}
@@ -16,6 +16,7 @@
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.template.impl.LiveTemplateLookupElement;
import com.intellij.patterns.PatternCondition;
import com.intellij.patterns.StandardPatterns;
import com.intellij.util.Consumer;
@@ -63,7 +64,7 @@ public class RelaxedMatchingContributor extends CompletionContributor {
}
CompletionParameters relaxed;
if (elements.isEmpty() && parameters.getInvocationCount() == 0) {
if (parameters.getInvocationCount() == 0 && (elements.isEmpty() || elements.size() == 1 && elements.iterator().next() instanceof LiveTemplateLookupElement)) {
relaxed = parameters.withRelaxedMatching();
}
else if (parameters.getInvocationCount() >= 2) {
@@ -29,11 +29,9 @@ import com.intellij.openapi.project.ProjectManagerAdapter;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.patterns.ElementPattern;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.Weigher;
import com.intellij.psi.WeighingService;
import com.intellij.psi.*;
import com.intellij.psi.impl.DebugUtil;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -82,7 +80,7 @@ public class CompletionServiceImpl extends CompletionService{
final PsiElement position = parameters.getPosition();
final String prefix = CompletionData.findPrefixStatic(position, parameters.getOffset());
final String textBeforePosition = parameters.getPosition().getContainingFile().getText().substring(0, parameters.getOffset());
return new CompletionResultSetImpl(consumer, textBeforePosition, new CamelHumpMatcher(prefix, true, parameters.relaxMatching()), contributor, defaultSorter(parameters), null);
return new CompletionResultSetImpl(consumer, textBeforePosition, new CamelHumpMatcher(prefix, true, parameters.relaxMatching()), contributor, parameters, defaultSorter(parameters), null);
}
@Override
@@ -108,16 +106,19 @@ public class CompletionServiceImpl extends CompletionService{
private static class CompletionResultSetImpl extends CompletionResultSet {
private final String myTextBeforePosition;
private final CompletionParameters myParameters;
private final CompletionSorterImpl mySorter;
@Nullable private final CompletionResultSetImpl myOriginal;
public CompletionResultSetImpl(final Consumer<LookupElement> consumer, final String textBeforePosition,
final PrefixMatcher prefixMatcher,
CompletionContributor contributor,
CompletionParameters parameters,
@NotNull CompletionSorterImpl sorter,
CompletionResultSetImpl original) {
super(prefixMatcher, consumer, contributor);
myTextBeforePosition = textBeforePosition;
myParameters = parameters;
mySorter = sorter;
myOriginal = original;
}
@@ -133,9 +134,13 @@ public class CompletionServiceImpl extends CompletionService{
if (!myTextBeforePosition.endsWith(matcher.getPrefix())) {
final int len = myTextBeforePosition.length();
final String fragment = len > 100 ? myTextBeforePosition.substring(len - 100) : myTextBeforePosition;
LOG.error("prefix should be some actual file string just before caret: " + matcher.getPrefix() + "\n text=" + fragment);
PsiFile positionFile = myParameters.getPosition().getContainingFile();
LOG.error("prefix should be some actual file string just before caret: " + matcher.getPrefix() +
"\n text=" + fragment +
"\ninjected=" + (InjectedLanguageUtil.getTopLevelFile(positionFile) != positionFile) +
"\nlang=" + positionFile.getLanguage());
}
return new CompletionResultSetImpl(getConsumer(), myTextBeforePosition, matcher, myContributor, mySorter, this);
return new CompletionResultSetImpl(getConsumer(), myTextBeforePosition, matcher, myContributor, myParameters, mySorter, this);
}
@Override
@@ -155,7 +160,7 @@ public class CompletionServiceImpl extends CompletionService{
@NotNull
@Override
public CompletionResultSet withRelevanceSorter(@NotNull CompletionSorter sorter) {
return new CompletionResultSetImpl(getConsumer(), myTextBeforePosition, getPrefixMatcher(), myContributor, (CompletionSorterImpl)sorter, this);
return new CompletionResultSetImpl(getConsumer(), myTextBeforePosition, getPrefixMatcher(), myContributor, myParameters, (CompletionSorterImpl)sorter, this);
}
@NotNull
@@ -287,28 +292,4 @@ public class CompletionServiceImpl extends CompletionService{
public CompletionSorterImpl emptySorter() {
return new CompletionSorterImpl(new ArrayList<ClassifierFactory<LookupElement>>());
}
private static class NegatingComparable<T extends NegatingComparable<T>> implements Comparable<T> {
private final Comparable myWeigh;
public NegatingComparable(Comparable weigh) {
myWeigh = weigh;
}
@Override
public int compareTo(T o) {
final Comparable w1 = myWeigh;
final Comparable w2 = o.myWeigh;
if (w1 == null && w2 == null) return 0;
if (w1 == null) return 1;
if (w2 == null) return -1;
return -w1.compareTo(w2);
}
@Override
public String toString() {
return String.valueOf(myWeigh);
}
}
}
@@ -0,0 +1,43 @@
/*
* Copyright 2000-2011 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.completion.impl;
/**
* @author peter
*/
public class NegatingComparable<T extends NegatingComparable<T>> implements Comparable<T> {
private final Comparable myWeigh;
public NegatingComparable(Comparable weigh) {
myWeigh = weigh;
}
@Override
public int compareTo(T o) {
final Comparable w1 = myWeigh;
final Comparable w2 = o.myWeigh;
if (w1 == null && w2 == null) return 0;
if (w1 == null) return 1;
if (w2 == null) return -1;
return -w1.compareTo(w2);
}
@Override
public String toString() {
return String.valueOf(myWeigh);
}
}
@@ -316,15 +316,21 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
hosts.addAll(elements1);
hosts.addAll(elements2);
PsiLanguageInjectionHost.InjectedPsiVisitor visitor = new PsiLanguageInjectionHost.InjectedPsiVisitor() {
final PsiLanguageInjectionHost.InjectedPsiVisitor visitor = new PsiLanguageInjectionHost.InjectedPsiVisitor() {
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
outInjected.add(injectedPsi);
synchronized (outInjected) {
outInjected.add(injectedPsi);
}
}
};
for (PsiElement element : hosts) {
progress.checkCanceled();
InjectedLanguageUtil.enumerate(element, myFile, visitor, false);
}
if (!JobUtil.invokeConcurrentlyUnderProgress(new ArrayList<PsiElement>(hosts), new Processor<PsiElement>() {
@Override
public boolean process(PsiElement element) {
progress.checkCanceled();
InjectedLanguageUtil.enumerate(element, myFile, visitor, false);
return true;
}
}, false, progress)) throw new ProcessCanceledException();
}
// returns false if canceled
@@ -53,7 +53,11 @@ public abstract class TailTypeDecorator<T extends LookupElement> extends LookupE
delegate.handleInsert(context);
if (tailType != null && tailType.isApplicable(context)) {
PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting();
tailType.processTail(context.getEditor(), context.getTailOffset());
int tailOffset = context.getTailOffset();
if (tailOffset < 0) {
throw new AssertionError("tailOffset < 0: delegate=" + getDelegate() + "; this=" + this + "; tail=" + tailType);
}
tailType.processTail(context.getEditor(), tailOffset);
}
}
@@ -581,7 +581,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
public Point calculatePosition(final JComponent component) {
Dimension dim = component.getPreferredSize();
int lookupStart = getLookupStart();
if (lookupStart < 0) {
if (lookupStart < 0 || lookupStart >= myEditor.getDocument().getTextLength()) {
LOG.error(lookupStart + "; offset=" + myEditor.getCaretModel().getOffset() + "; element=" +
getPsiElement());
}
@@ -593,7 +593,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
JComponent internalComponent = myEditor.getContentComponent();
final JRootPane rootPane = editorComponent.getRootPane();
if (rootPane == null) {
LOG.error(myEditor.isDisposed());
LOG.error(myEditor.isDisposed() + "; shown=" + myShown + "; disposed=" + myDisposed + "; editorShowing=" + myEditor.getContentComponent().isShowing());
}
JLayeredPane layeredPane = rootPane.getLayeredPane();
Point layeredPanePoint=SwingUtilities.convertPoint(internalComponent,location, layeredPane);
@@ -670,6 +670,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
}
public int getLookupStart() {
LOG.assertTrue(myLookupStartMarker.isValid());
return myLookupStartMarker.getStartOffset();
}
@@ -683,6 +684,8 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
finally {
myChangeGuard = false;
}
LOG.assertTrue(!myDisposed, disposeTrace);
LOG.assertTrue(myLookupStartMarker.isValid());
if (isVisible()) {
updateLookupBounds();
}
@@ -807,6 +810,10 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
}
myElementHint = null;
}
if (!isFocused()) {
return;
}
final Collection<LookupElementAction> actions = myModel.getActionsFor(item);
if (!actions.isEmpty()) {
myHintAlarm.addRequest(new Runnable() {
@@ -59,6 +59,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.Navigatable;
import com.intellij.psi.*;
@@ -66,9 +67,12 @@ import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.search.searches.DefinitionsSearch;
import com.intellij.psi.util.PsiUtilBase;
import com.intellij.ui.LightweightHint;
import com.intellij.usageView.UsageViewShortNameLocation;
import com.intellij.usageView.UsageViewTypeLocation;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
import java.awt.*;
@@ -85,7 +89,6 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
private final FileEditorManager myFileEditorManager;
private enum BrowseMode {None, Declaration, TypeDeclaration, Implementation}
private final KeyListener myEditorKeyListener = new KeyAdapter() {
public void keyPressed(final KeyEvent e) {
handleKey(e);
@@ -226,6 +229,11 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
return false;
}
@TestOnly
public static String getInfo(PsiElement element, PsiElement atPointer) {
return generateInfo(element, atPointer);
}
@Nullable
private static String generateInfo(PsiElement element, PsiElement atPointer) {
final DocumentationProvider documentationProvider = DocumentationManager.getProviderFromElement(element, atPointer);
@@ -242,6 +250,11 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
}
}
info = getQuickNavigateInfo(element);
if (info != null) {
return info;
}
if (element instanceof NavigationItem) {
final ItemPresentation presentation = ((NavigationItem)element).getPresentation();
if (presentation != null) {
@@ -252,6 +265,21 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
return null;
}
@Nullable
private static String getQuickNavigateInfo(PsiElement element) {
final String name = ElementDescriptionUtil.getElementDescription(element, UsageViewShortNameLocation.INSTANCE);
if (StringUtil.isEmpty(name)) return null;
final String typeName = ElementDescriptionUtil.getElementDescription(element, UsageViewTypeLocation.INSTANCE);
final PsiFile file = element.getContainingFile();
final StringBuilder sb = new StringBuilder();
if (StringUtil.isNotEmpty(typeName)) sb.append(typeName).append(" ");
sb.append("\"").append(name).append("\"");
if (file != null && file.isPhysical()) {
sb.append(" [").append(file.getName()).append("]");
}
return sb.toString();
}
private abstract static class Info {
@NotNull protected final PsiElement myElementAtPointer;
private final List<TextRange> myRanges;
@@ -0,0 +1,33 @@
/*
* Copyright 2000-2011 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.template.impl;
import com.intellij.codeInsight.lookup.CharFilter;
import com.intellij.codeInsight.lookup.Lookup;
/**
* @author peter
*/
public class LiveTemplateCharFilter extends CharFilter {
@Override
public Result acceptChar(char c, int prefixLength, Lookup lookup) {
if (lookup.getCurrentItem() instanceof LiveTemplateLookupElement && c != ' ') {
return Result.HIDE_LOOKUP;
}
return null;
}
}
@@ -16,9 +16,6 @@
package com.intellij.codeInsight.template.impl;
import com.intellij.codeInsight.completion.*;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.codeInsight.template.TemplateManager;
import com.intellij.openapi.util.Condition;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.PsiFile;
@@ -48,14 +45,7 @@ public class LiveTemplateCompletionContributor extends CompletionContributor {
final String prefix = result.getPrefixMatcher().getPrefix();
final TemplateImpl template = findApplicableTemplate(file, offset, prefix);
if (template != null) {
result.addElement(LookupElementBuilder.create(prefix).setTypeText(template.getDescription()).setInsertHandler(new InsertHandler<LookupElement>() {
@Override
public void handleInsert(InsertionContext context, LookupElement item) {
context.getDocument().deleteString(context.getStartOffset(), context.getTailOffset());
context.setAddCompletionChar(false);
TemplateManager.getInstance(context.getProject()).startTemplate(context.getEditor(), template);
}
}));
result.addElement(new LiveTemplateLookupElement(prefix, template));
} else {
for (final TemplateImpl possible : listApplicableTemplates(file, offset)) {
result.restartCompletionOnPrefixChange(possible.getKey());
@@ -0,0 +1,53 @@
/*
* Copyright 2000-2011 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.template.impl;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementPresentation;
import com.intellij.codeInsight.template.TemplateManager;
import org.jetbrains.annotations.NotNull;
/**
* @author peter
*/
public class LiveTemplateLookupElement extends LookupElement {
private final String myPrefix;
private final TemplateImpl myTemplate;
public LiveTemplateLookupElement(String prefix, TemplateImpl template) {
myPrefix = prefix;
myTemplate = template;
}
@NotNull
@Override
public String getLookupString() {
return myPrefix;
}
@Override
public void renderElement(LookupElementPresentation presentation) {
super.renderElement(presentation);
presentation.setTypeText(myTemplate.getDescription());
}
@Override
public void handleInsert(InsertionContext context) {
context.getDocument().deleteString(context.getStartOffset(), context.getTailOffset());
context.setAddCompletionChar(false);
TemplateManager.getInstance(context.getProject()).startTemplate(context.getEditor(), myTemplate);
}
}
@@ -60,9 +60,8 @@ public class ConsoleExecuteActionHandler {
languageConsole.addCurrentToHistory(range, false, myPreserveMarkup);
}
languageConsole.setInputText("");
if (!StringUtil.isEmptyOrSpaces(text)) {
myConsoleHistoryModel.addToHistory(text);
}
myConsoleHistoryModel.addToHistory(text);
// Send to interpreter / server
processLine(text);
@@ -28,12 +28,13 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.containers.CollectionFactory;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
/**
@@ -43,7 +44,7 @@ public abstract class GotoActionBase extends AnAction {
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.GotoActionBase");
protected static Class myInAction = null;
private static Map<Class, String> ourLastStrings = new HashMap<Class, String>();
private static Map<Class, Pair<String, Integer>> ourLastStrings = CollectionFactory.hashMap();
public final void actionPerformed(AnActionEvent e) {
@@ -98,22 +99,22 @@ public abstract class GotoActionBase extends AnAction {
public abstract void elementChosen(ChooseByNamePopup popup, Object element);
}
private static String getInitialText(Editor editor) {
private static Pair<String, Integer> getInitialText(Editor editor) {
if (editor != null) {
final String selectedText = editor.getSelectionModel().getSelectedText();
if (selectedText != null && selectedText.indexOf("\n") < 0) {
return selectedText;
return Pair.create(selectedText, 0);
}
}
if (myInAction != null) {
final String lastString = ourLastStrings.get(myInAction);
final Pair<String, Integer> lastString = ourLastStrings.get(myInAction);
if (lastString != null) {
return lastString;
}
}
return "";
return Pair.create("", 0);
}
protected static <T> void showNavigationPopup(AnActionEvent e, ChooseByNameModel model, final GotoActionCallback<T> callback) {
@@ -122,14 +123,15 @@ public abstract class GotoActionBase extends AnAction {
boolean mayRequestOpenInCurrentWindow = model.willOpenEditor() && FileEditorManagerEx.getInstanceEx(project).hasSplitOrUndockedWindows();
final Class startedAction = myInAction;
LOG.assertTrue(startedAction != null);
final ChooseByNamePopup popup = ChooseByNamePopup.createPopup(project, model, getPsiContext(e), getInitialText(e.getData(PlatformDataKeys.EDITOR)), mayRequestOpenInCurrentWindow);
Pair<String, Integer> start = getInitialText(e.getData(PlatformDataKeys.EDITOR));
final ChooseByNamePopup popup = ChooseByNamePopup.createPopup(project, model, getPsiContext(e), start.first, mayRequestOpenInCurrentWindow, start.second);
final ChooseByNameFilter<T> filter = callback.createFilter(popup);
popup.invoke(new ChooseByNamePopupComponent.Callback() {
@Override
public void onClose() {
ourLastStrings.put(myInAction, popup.getEnteredText());
ourLastStrings.put(myInAction, Pair.create(popup.getEnteredText(), popup.getSelectedIndex()));
if (startedAction.equals(myInAction)) {
myInAction = null;
}
@@ -342,6 +342,7 @@ public class FileStructureDialog extends DialogWrapper {
myList.repaint(); // to update match highlighting
}
});
myListSpeedSearch.setComparator(createSpeedSearchComparator());
}
private boolean hasPrefixShortened(final PropertyChangeEvent evt) {
@@ -412,7 +413,7 @@ public class FileStructureDialog extends DialogWrapper {
}
ArrayList<Object> filteredElements = new ArrayList<Object>(childElements.length);
SpeedSearchBase.SpeedSearchComparator speedSearchComparator = new SpeedSearchBase.SpeedSearchComparator();
SpeedSearchBase.SpeedSearchComparator speedSearchComparator = createSpeedSearchComparator();
for (Object child : childElements) {
if (child instanceof AbstractTreeNode) {
@@ -438,6 +439,10 @@ public class FileStructureDialog extends DialogWrapper {
}
}
private static SpeedSearchBase.SpeedSearchComparator createSpeedSearchComparator() {
return new SpeedSearchBase.SpeedSearchComparator(false);
}
private class MyTreeActionsOwner implements TreeActionsOwner {
private final Set<Filter> myFilters = new HashSet<Filter>();
@@ -29,10 +29,7 @@ import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.ui.ColoredTreeCellRenderer;
import com.intellij.ui.NonFocusableCheckBox;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.TreeSpeedSearch;
import com.intellij.ui.*;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.Icons;
import com.intellij.util.SmartList;
@@ -306,6 +303,7 @@ public class MemberChooser<T extends ClassMember> extends DialogWrapper implemen
return delegate.getText();
}
});
treeSpeedSearch.setComparator(new SpeedSearchBase.SpeedSearchComparator(false));
treeSpeedSearch.addChangeListener(new PropertyChangeListener() {
@Override
@@ -131,6 +131,7 @@ public abstract class ChooseByNameBase {
protected JBPopup myDropdownPopup;
private boolean myClosedByShiftEnter = false;
protected final int myInitialIndex;
private static class MatchesComparator implements Comparator<String> {
private final String myOriginalPattern;
@@ -154,10 +155,20 @@ public abstract class ChooseByNameBase {
* @param context
*/
protected ChooseByNameBase(Project project, ChooseByNameModel model, String initialText, final PsiElement context) {
this(project, model, initialText, context, 0);
}
/**
* @param initialText initial text which will be in the lookup text field
* @param context
* @param initialIndex
*/
protected ChooseByNameBase(Project project, ChooseByNameModel model, String initialText, final PsiElement context, final int initialIndex) {
myProject = project;
myModel = model;
myInitialText = initialText;
myContext = new WeakReference<PsiElement>(context);
myInitialIndex = initialIndex;
}
public boolean isPreselectInitialText() {
@@ -418,7 +429,7 @@ public abstract class ChooseByNameBase {
myCheckBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
rebuildList();
rebuildList(false);
}
});
myCheckBox.setFocusable(false);
@@ -426,7 +437,7 @@ public abstract class ChooseByNameBase {
myTextField.getDocument().addDocumentListener(new DocumentAdapter() {
protected void textChanged(DocumentEvent e) {
clearPosponedOkAction(false);
rebuildList();
rebuildList(false);
}
});
@@ -514,7 +525,7 @@ public abstract class ChooseByNameBase {
showTextFieldPanel();
if (modalityState != null) {
rebuildList(0, 0, null, modalityState, null);
rebuildList(myInitialIndex, 0, null, modalityState, null);
}
}
@@ -528,9 +539,9 @@ public abstract class ChooseByNameBase {
/**
* Default rebuild list. It uses {@link #REBUILD_DELAY} and current modality state.
*/
public void rebuildList() {
public void rebuildList(boolean initial) {
// TODO this method is public, because the chooser does not listed for the model.
rebuildList(0, REBUILD_DELAY, null, ModalityState.current(), null);
rebuildList(initial ? myInitialIndex : 0, REBUILD_DELAY, null, ModalityState.current(), null);
}
private void updateDocumentation() {
@@ -577,7 +588,7 @@ public abstract class ChooseByNameBase {
return false;
}
protected boolean isToFixLostTyping() {
protected static boolean isToFixLostTyping() {
return Registry.is("actionSystem.fixLostTyping");
}
@@ -793,7 +804,7 @@ public abstract class ChooseByNameBase {
myListUpdater.appendToModel(commands, pos);
}
else {
if (pos == 0) {
if (pos <= 0) {
pos = detectBestStatisticalPosition();
}
@@ -915,7 +926,7 @@ public abstract class ChooseByNameBase {
myList.setVisibleRowCount(Math.min(VISIBLE_LIST_SIZE_LIMIT, myList.getModel().getSize()));
if (!myListModel.isEmpty()) {
int pos = selectionPos == 0 ? detectBestStatisticalPosition() : selectionPos;
int pos = selectionPos <= 0 ? detectBestStatisticalPosition() : selectionPos;
ListScrollingUtil.selectItem(myList, Math.min(pos, myListModel.size() - 1));
}
@@ -1116,7 +1127,7 @@ public abstract class ChooseByNameBase {
myTextField.setText(newPattern);
myTextField.setCaretPosition(newPattern.length());
rebuildList();
rebuildList(false);
}
private boolean isComplexPattern(final String pattern) {
@@ -173,11 +173,11 @@ public abstract class ChooseByNameFilter<T> {
chooser.setElementMarked(type, false);
}
}
updateModel(model, chooser);
updateModel(model, chooser, true);
chooser.addElementsMarkListener(new ElementsChooser.ElementsMarkListener<T>() {
public void elementMarkChanged(final T element, final boolean isMarked) {
filterConfiguration.setVisible(element, isMarked);
updateModel(model, chooser);
updateModel(model, chooser, false);
}
});
return chooser;
@@ -197,10 +197,10 @@ public abstract class ChooseByNameFilter<T> {
* @param gotoFileModel a model
* @param chooser a file type chooser
*/
protected void updateModel(final FilteringGotoByModel<T> gotoFileModel, ElementsChooser<T> chooser) {
protected void updateModel(final FilteringGotoByModel<T> gotoFileModel, ElementsChooser<T> chooser, boolean initial) {
final List<T> markedElements = chooser.getMarkedElements();
gotoFileModel.setFilterItems(markedElements);
myParentPopup.rebuildList();
myParentPopup.rebuildList(initial);
}
/**
@@ -51,8 +51,8 @@ public class ChooseByNamePopup extends ChooseByNameBase implements ChooseByNameP
private boolean myMayRequestCurrentWindow;
protected ChooseByNamePopup(final Project project, final ChooseByNameModel model, final ChooseByNamePopup oldPopup,
final PsiElement context, @Nullable final String predefinedText, boolean mayRequestOpenInCurrentWundow) {
super(project, model, oldPopup != null ? oldPopup.getEnteredText() : predefinedText, context);
final PsiElement context, @Nullable final String predefinedText, boolean mayRequestOpenInCurrentWundow, int initialIndex) {
super(project, model, oldPopup != null ? oldPopup.getEnteredText() : predefinedText, context, initialIndex);
if (oldPopup == null && predefinedText != null) {
setPreselectInitialText(true);
}
@@ -66,11 +66,15 @@ public class ChooseByNamePopup extends ChooseByNameBase implements ChooseByNameP
return myTextField.getText();
}
public int getSelectedIndex() {
return myList.getSelectedIndex();
}
protected void initUI(final Callback callback, final ModalityState modalityState, boolean allowMultipleSelection) {
super.initUI(callback, modalityState, allowMultipleSelection);
//LaterInvocator.enterModal(myTextFieldPanel);
if (myInitialText != null) {
rebuildList(0, 0, null, ModalityState.current(), null);
rebuildList(myInitialIndex, 0, null, ModalityState.current(), null);
}
if (myOldFocusOwner != null){
myPreviouslyFocusedComponent = myOldFocusOwner;
@@ -228,18 +232,19 @@ public class ChooseByNamePopup extends ChooseByNameBase implements ChooseByNameP
}
public static ChooseByNamePopup createPopup(final Project project, final ChooseByNameModel model, final PsiElement context,
@Nullable final String predefinedText) {
return createPopup(project, model, context, predefinedText, false);
return createPopup(project, model, context, predefinedText, false, 0);
}
public static ChooseByNamePopup createPopup(final Project project, final ChooseByNameModel model, final PsiElement context,
@Nullable final String predefinedText,
boolean mayRequestOpenInCurrentWindow) {
boolean mayRequestOpenInCurrentWindow, final int initialIndex) {
final ChooseByNamePopup oldPopup = project.getUserData(CHOOSE_BY_NAME_POPUP_IN_PROJECT_KEY);
if (oldPopup != null) {
oldPopup.close(false);
}
ChooseByNamePopup newPopup = new ChooseByNamePopup(project, model, oldPopup, context, predefinedText, mayRequestOpenInCurrentWindow);
ChooseByNamePopup newPopup = new ChooseByNamePopup(project, model, oldPopup, context, predefinedText, mayRequestOpenInCurrentWindow,
initialIndex);
project.putUserData(CHOOSE_BY_NAME_POPUP_IN_PROJECT_KEY, newPopup);
return newPopup;
@@ -646,6 +646,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider {
private class MyTreeSelectionListener implements TreeSelectionListener {
private final TextAttributes myAttributes;
private RangeHighlighter myHighlighter;
public MyTreeSelectionListener() {
myAttributes = new TextAttributes();
@@ -656,11 +657,8 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider {
public void valueChanged(TreeSelectionEvent e) {
if (!myEditor.getDocument().getText().equals(myLastParsedText)) return;
TreePath path = myTree.getSelectionPath();
if (path == null) {
clearSelection();
}
else {
clearSelection();
clearSelection();
if (path != null) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
if (!(node.getUserObject() instanceof ViewerNodeDescriptor)) return;
ViewerNodeDescriptor descriptor = (ViewerNodeDescriptor)node.getUserObject();
@@ -684,8 +682,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider {
final int textLength = myEditor.getDocument().getTextLength();
if (end <= textLength) {
myEditor.getMarkupModel()
.addRangeHighlighter(start, end, HighlighterLayer.LAST, myAttributes, HighlighterTargetArea.EXACT_RANGE);
myHighlighter = myEditor.getMarkupModel().addRangeHighlighter(start, end, HighlighterLayer.LAST, myAttributes, HighlighterTargetArea.EXACT_RANGE);
if (myTree.hasFocus()) {
myEditor.getCaretModel().moveToOffset(start);
myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
@@ -716,7 +713,10 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider {
}
private void clearSelection() {
myEditor.getMarkupModel().removeAllHighlighters();
if (myHighlighter != null) {
myEditor.getMarkupModel().removeHighlighter(myHighlighter);
myHighlighter.dispose();
}
}
}
@@ -149,9 +149,9 @@ public class TodoCheckinHandler extends CheckinHandler {
}
};
final boolean completed = ProgressManager.getInstance().runProcessWithProgressSynchronously(runnable, "Looking for new and edited TODO items...", true, myProject);
if (! completed || (worker.getAddedOrEditedTodos().isEmpty() && worker.getInChangedTodos().isEmpty() &&
if (completed && (worker.getAddedOrEditedTodos().isEmpty() && worker.getInChangedTodos().isEmpty() &&
worker.getSkipped().isEmpty())) return ReturnResult.COMMIT;
if (! completed) return ReturnResult.CANCEL;
return showResults(worker, executor);
}
@@ -34,6 +34,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
@@ -104,8 +105,11 @@ public class TodoCheckinHandlerWorker {
for (Change change : changes) {
ProgressManager.checkCanceled();
if (change.getAfterRevision() == null) continue;
final VirtualFile afterFile = change.getAfterRevision().getFile().getVirtualFile();
if (afterFile.isDirectory() || afterFile.getFileType().isBinary()) continue;
VirtualFile afterFile = change.getAfterRevision().getFile().getVirtualFile();
if (afterFile == null) {
afterFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(change.getAfterRevision().getFile().getIOFile());
}
if (afterFile == null || afterFile.isDirectory() || afterFile.getFileType().isBinary()) continue;
myPsiFile = null;
if (afterFile.isValid()) {
@@ -623,7 +623,7 @@ public class PsiDocumentManagerImpl extends PsiDocumentManager implements Projec
// Consider that it's worth to perform complete re-parse instead of merge if the whole document text is replaced and
// current document lines number is roughly above 5000. This makes sense in situations when external change is performed
// for the huge file (that causes the whole document to be reloaded and 'merge' way takes a while to complete).
if (event.isWholeTextReplaced() && document.getTextLength() > 500000) {
if (event.isWholeTextReplaced() && document.getTextLength() > 100000) {
document.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, Boolean.TRUE);
}
@@ -217,6 +217,9 @@ public class PostprocessReformattingAspect implements PomModelAspect, Disposable
doPostponedFormatting(viewProvider);
}
}
catch (Exception e) {
LOG.error(e);
}
finally {
LOG.assertTrue(myReformatElements.isEmpty());
}
@@ -240,6 +240,7 @@ public class LazyParseablePsiElement extends LazyParseableElement implements Psi
@NotNull
public GlobalSearchScope getResolveScope() {
assert isValid();
return getManager().getFileManager().getResolveScope(this);
}
@@ -0,0 +1,51 @@
/*
* Copyright 2000-2011 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.refactoring.rename;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.project.Project;
import com.intellij.patterns.ElementPattern;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.Nullable;
/**
* User: anna
* Date: 4/5/11
*/
public class RenameToIgnoredDirectoryFileInputValidator implements RenameInputValidatorEx {
@Nullable
@Override
public String getErrorMessage(String newName, Project project) {
if (FileTypeManager.getInstance().isFileIgnored(newName)) {
return "Trying to create a directory with ignored name, result will not be visible";
}
return null;
}
@Override
public ElementPattern<? extends PsiElement> getPattern() {
return PlatformPatterns.or(PlatformPatterns.psiElement(PsiDirectory.class), PlatformPatterns.psiElement(PsiFile.class));
}
@Override
public boolean isInputValid(String newName, PsiElement element, ProcessingContext context) {
return newName != null && newName.length() > 0;
}
}
@@ -32,6 +32,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
@@ -95,6 +96,7 @@ public class VariableInplaceRenamer {
private ArrayList<RangeHighlighter> myHighlighters;
private final Editor myEditor;
private final Project myProject;
private RangeMarker myRenameOffset;
public void setAdvertisementText(String advertisementText) {
myAdvertisementText = advertisementText;
@@ -108,6 +110,7 @@ public class VariableInplaceRenamer {
myElementToRename = elementToRename;
myEditor = /*(editor instanceof EditorWindow)? ((EditorWindow)editor).getDelegate() : */editor;
myProject = myElementToRename.getProject();
myRenameOffset = myEditor.getDocument().createRangeMarker(myElementToRename.getTextRange());
}
public boolean performInplaceRename() {
@@ -230,7 +233,6 @@ public class VariableInplaceRenamer {
addAdditionalVariables(builder);
final PsiElement scope1 = scope;
final int renameOffset = myElementToRename.getTextOffset();
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@@ -268,11 +270,10 @@ public class VariableInplaceRenamer {
@Override
public void templateFinished(Template template, boolean brokenOff) {
super.templateFinished(template, brokenOff);
if (myNewName != null) {
performAutomaticRename(myNewName, PsiTreeUtil.getParentOfType(containingFile.findElementAt(renameOffset),
PsiNameIdentifierOwner.class));
}
moveOffsetAfter(!brokenOff);
if (myNewName != null) {
performAutomaticRename(myNewName, getVariable());
}
}
public void templateCancelled(Template template) {
@@ -318,6 +319,16 @@ public class VariableInplaceRenamer {
return null;
}
@Nullable
protected PsiNamedElement getVariable() {
if (myElementToRename != null && myElementToRename.isValid()) return myElementToRename;
final PsiFile psiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(myEditor.getDocument());
if (psiFile != null) {
return PsiTreeUtil.getParentOfType(psiFile.findElementAt(myRenameOffset.getStartOffset()), PsiNameIdentifierOwner.class);
}
return myElementToRename;
}
protected void moveOffsetAfter(boolean success) {
}
@@ -251,7 +251,7 @@ public class Messages {
new PairFunction<Integer, JCheckBox, Integer>() {
@Override
public Integer fun(final Integer exitCode, final JCheckBox cb) {
return exitCode == CANCEL ? CANCEL : exitCode + (cb.isSelected() ? 1 : 0);
return exitCode == -1 ? CANCEL : exitCode + (cb.isSelected() ? 1 : 0);
}
});
}
@@ -20,19 +20,61 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author peter
* A helper object for {@link RecursionManager}. Is obtained from {@link RecursionManager#createGuard(String)}.
*
* @author peter
*/
public interface RecursionGuard {
/**
* @param key an id of the computation. Is stored internally to ensure that a recursive calls with the same key won't lead to endless recursion.
* @param computation a piece of code to compute.
* @return the result of the computation or null if we're entering a computation with this key on this thread recursively,
*/
@Nullable
<T> T doPreventingRecursion(Object key, Computable<T> computation);
/**
* Used in pair with {@link com.intellij.openapi.util.RecursionGuard.StackStamp#mayCacheNow()} to ensure that cached are only the reliable values,
* not depending on anything incomplete due to recursive prevention policies.
* A typical usage is this:
* <code>
* RecursionGuard.StackStamp stamp = RecursionManager.createGuard("id").markStack();
*
* Result result = doComputation();
*
* if (stamp.mayCacheNow()) {
* cache(result);
* }
* return result;
* </code>
* @return an object representing the current stack state, managed by {@link RecursionManager}
*/
StackStamp markStack();
/**
* @return the current thread-local stack of keys passed to {@link #doPreventingRecursion(Object, Computable)}
*/
List<Object> currentStack();
/**
* Makes {@link com.intellij.openapi.util.RecursionGuard.StackStamp#mayCacheNow()} return false for all stamps created since a computation with
* key <code>since</code> began.
*
* Used to prevent caching of results that are non-reliable NOT due to recursion prevention: for example, too deep recursion
* ({@link #currentStack()} may help in determining the recursion depth)
*
* @param since the id of a computation whose result is safe to cache whilst for more nested ones it's not.
*/
void prohibitResultCaching(Object since);
interface StackStamp {
/**
* @return whether a computation that started at the moment of this {@link StackStamp} instance creation does not depend on any re-entrant recursive
* results. When such non-reliable results exist in the thread's call stack, returns false, otherwise true
*/
boolean mayCacheNow();
}
}
@@ -21,6 +21,22 @@ import java.util.List;
import java.util.Map;
/**
* There are moments when a computation A requires the result of computation B, which in turn requires C, which (unexpectedly) requires A.
* If there are no other ways to solve it, it helps to track all the computations in the thread stack and return some default value when
* asked to compute A for the second time. {@link RecursionGuard#doPreventingRecursion(Object, Computable)} does precisely this.
*
* It's quite useful to cache some computation results to avoid performance problems. But not everyone realises that in the above situation it's
* incorrect to cache the results of B and C, because they all are based on the default incomplete result of the A calculation. If the actual
* computation sequence were C->A->B->C, the result of the outer C most probably wouldn't be the same as in A->B->C->A, where it depends on
* the null A result directly. The natural wish is that the program with cache enabled has the same results as the one without cache. In the above
* situation the result of C would depend on the order of invocations of C and A, which can be hardly predictable in multithreaded environments.
*
* Therefore if you use any kind of cache, it probably would make your program safer to cache only when it's safe to do this. See
* {@link com.intellij.openapi.util.RecursionGuard#markStack()} and {@link com.intellij.openapi.util.RecursionGuard.StackStamp#mayCacheNow()}
* for the advice.
*
* @see RecursionGuard
* @see RecursionGuard.StackStamp
* @author peter
*/
@SuppressWarnings({"UtilityClassWithoutPrivateConstructor"})
@@ -38,6 +54,10 @@ public class RecursionManager {
}
};
/**
* @param id just some string to separate different recursion prevention policies from each other
* @return a helper object which allow you to perform reentrancy-safe computations and check whether caching will be safe.
*/
public static RecursionGuard createGuard(final String id) {
return new RecursionGuard() {
@Override
@@ -25,17 +25,19 @@ import java.awt.*;
* Date: 08-Nov-2005
*/
public class DottedBorder implements Border {
private final Insets myInsets;
private final int myTop, myBottom, myLeft, myRight;
private final Color myColor;
public DottedBorder(Insets insets, Color color) {
myInsets = insets;
myTop = insets.top;
myBottom = insets.bottom;
myLeft = insets.left;
myRight = insets.right;
myColor = color;
}
public DottedBorder(Color color) {
myInsets = new Insets(1, 1, 1, 1);
myColor = color;
this(new Insets(1, 1, 1, 1), color);
}
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
@@ -44,7 +46,8 @@ public class DottedBorder implements Border {
}
public Insets getBorderInsets(Component c) {
return myInsets;
//return a copy, otherwise someone could change our insets from outside
return new Insets(myTop, myLeft, myBottom, myRight);
}
public boolean isBorderOpaque() {
@@ -2,6 +2,7 @@ package com.intellij.execution.process;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.util.ModificationTracker;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
@@ -21,11 +22,14 @@ public class ConsoleHistoryModel implements ModificationTracker {
public void addToHistory(final String statement) {
final int maxHistorySize = getMaxHistorySize();
synchronized (myHistory) {
removeFromHistory(statement);
if (myHistory.size() >= maxHistorySize) {
myHistory.removeLast();
myHistoryCursor = -1;
if (!StringUtil.isEmptyOrSpaces(statement)) {
removeFromHistory(statement);
if (myHistory.size() >= maxHistorySize) {
myHistory.removeLast();
}
myHistory.addFirst(statement);
}
myHistory.addFirst(statement);
}
}
@@ -36,7 +40,7 @@ public class ConsoleHistoryModel implements ModificationTracker {
public void removeFromHistory(final String statement) {
synchronized (myHistory) {
myModificationTracker++;
myHistoryCursor = -1;
myHistory.remove(statement);
}
}
@@ -22,6 +22,7 @@ import com.intellij.ide.actions.AboutAction;
import com.intellij.ide.actions.OpenFileAction;
import com.intellij.ide.impl.ProjectUtil;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.options.ConfigurableGroup;
@@ -31,14 +32,34 @@ import com.intellij.openapi.options.ex.ProjectConfigurablesGroup;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.mac.foundation.Foundation;
import com.intellij.ui.mac.foundation.ID;
import com.sun.jna.Callback;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.event.MouseEvent;
import java.io.File;
/**
* @author max
*/
public class MacOSApplicationProvider implements ApplicationComponent {
private static final Callback IMPL = new Callback() {
public void callback(ID self, String selector) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
ActionManagerEx am = ActionManagerEx.getInstanceEx();
MouseEvent me =
new MouseEvent(JOptionPane.getRootFrame(), MouseEvent.MOUSE_CLICKED, System.currentTimeMillis(), 0, 0, 0, 1, false);
am.tryToExecute(am.getAction("CheckForUpdate"), me, null, null, false);
}
});
}
};
@NotNull
public String getComponentName() {
return "MACOSApplicationProvider";
@@ -108,6 +129,34 @@ public class MacOSApplicationProvider implements ApplicationComponent {
application.addPreferencesMenuItem();
application.setEnabledAboutMenu(true);
application.setEnabledPreferencesMenu(true);
installAutoUpdateMenu();
}
private static void installAutoUpdateMenu() {
ID pool = Foundation.invoke("NSAutoreleasePool", "new");
ID app = Foundation.invoke("NSApplication", "sharedApplication");
ID menu = Foundation.invoke(app, Foundation.createSelector("menu"));
ID item = Foundation.invoke(menu, Foundation.createSelector("itemAtIndex:"), 0);
ID appMenu = Foundation.invoke(item, Foundation.createSelector("submenu"));
final ID checkForUpdatesClass = Foundation.registerObjcClass(Foundation.getClass("NSMenuItem"), "NSCheckForUpdates");
Foundation.addMethod(checkForUpdatesClass, Foundation.createSelector("checkForUpdates"), IMPL, "v");
Foundation.registerObjcClassPair(checkForUpdatesClass);
ID checkForUpdates = Foundation.invoke("NSCheckForUpdates", "alloc");
Foundation.invoke(checkForUpdates, Foundation.createSelector("initWithTitle:action:keyEquivalent:"), Foundation.cfString("Check for Updates..."),
Foundation.createSelector("checkForUpdates"), Foundation.cfString(""));
Foundation.invoke(checkForUpdates, Foundation.createSelector("setTarget:"), checkForUpdates);
Foundation.invoke(appMenu, Foundation.createSelector("insertItem:atIndex:"), checkForUpdates, 1);
Foundation.invoke(checkForUpdates, Foundation.createSelector("release"));
Foundation.invoke(pool, Foundation.createSelector("release"));
}
private static Project getProject() {
@@ -31,6 +31,11 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
public class CheckForUpdateAction extends AnAction implements DumbAware {
public void update(AnActionEvent e) {
e.getPresentation().setVisible(!SystemInfo.isMacSystemMenu);
}
public void actionPerformed(AnActionEvent e) {
Project project = e.getData(PlatformDataKeys.PROJECT);
actionPerformed(project, true, null);
@@ -381,7 +381,7 @@
<weigher key="completionSorting" implementationClass="com.intellij.codeInsight.completion.PriorityWeigher$Negative" id="sPriority" order="first"/>
<weigher key="completionSorting" implementationClass="com.intellij.codeInsight.completion.GroupingWeigher" id="sGrouping" order="after sPriority"/>
<weigher key="completionSorting" implementationClass="com.intellij.codeInsight.completion.LookupStringWeigher" id="sLookupString" order="after sGrouping"/>
<weigher key="completionSorting" implementationClass="com.intellij.codeInsight.completion.LookupElementProximityWeigher" id="sProximity" order="after sLookupString"/>
<weigher key="completionSorting" implementationClass="com.intellij.codeInsight.completion.LookupElementProximityWeigher$Negative" id="sProximity" order="after sLookupString"/>
<completion.contributor language="any" implementationClass="com.intellij.codeInsight.completion.RelaxedMatchingContributor" id="inexactMatching" order="first"/>
<completion.contributor language="any" implementationClass="com.intellij.codeInsight.completion.DefaultCompletionContributor" id="default" order="last"/>
@@ -402,6 +402,7 @@
<psi.referenceContributor implementation="com.intellij.psi.PsiReferenceContributorImpl"/>
<lookup.charFilter implementation="com.intellij.codeInsight.template.impl.LiveTemplateCharFilter" order="first" id="liveTemplate"/>
<lookup.charFilter implementation="com.intellij.codeInsight.completion.CompletionCharFilter" order="last" id="completion"/>
<lookup.charFilter implementation="com.intellij.refactoring.IdentifierCharFilter" id="identifier"/>
<lookup.charFilter implementation="com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceCharFilter" id="fileRef" order="before completion"/>
@@ -618,6 +619,7 @@
<statistics.usagesCollector implementation="com.intellij.facet.impl.statistics.FrameworkUsagesCollector"/>
<renamePsiElementProcessor implementation="com.intellij.refactoring.rename.RenamePsiFileProcessor" order="last"/>
<renameInputValidator implementation="com.intellij.refactoring.rename.RenameToIgnoredDirectoryFileInputValidator" order="last"/>
<refactoring.elementListenerProvider implementation="com.intellij.execution.impl.RunConfigurationRefactoringElementListenerProvider"/>
</extensions>
@@ -30,7 +30,7 @@ public abstract class FieldCache<T, Owner,AccessorParameter,Parameter> {
w = ourLock.writeLock();
}
public final T get(AccessorParameter a, Owner owner, Parameter p) {
public T get(AccessorParameter a, Owner owner, Parameter p) {
r.lock();
T result;
try {
@@ -68,7 +68,7 @@ public abstract class FieldCache<T, Owner,AccessorParameter,Parameter> {
}
}
public final void clear(AccessorParameter a, Owner owner) {
public void clear(AccessorParameter a, Owner owner) {
w.lock();
try {
putValue(null, owner, a);
@@ -81,4 +81,4 @@ public abstract class FieldCache<T, Owner,AccessorParameter,Parameter> {
protected abstract T compute(Owner owner, Parameter p);
protected abstract T getValue(Owner owner, AccessorParameter p);
protected abstract void putValue(T t, Owner owner, AccessorParameter p);
}
}
@@ -44,4 +44,19 @@ public abstract class UserDataCache<T, Owner extends UserDataHolder, Param> exte
protected final void putValue(final T t, final Owner owner, final Key<T> key) {
owner.putUserData(key, t);
}
@Override
public T get(Key<T> a, Owner owner, Param p) {
T value = owner.getUserData(a);
if (value == null) {
value = compute(owner, p);
value = ((UserDataHolderEx)owner).putUserDataIfAbsent(a, value);
}
return value;
}
@Override
public void clear(Key<T> key, Owner owner) {
owner.putUserData(key, null);
}
}
@@ -505,6 +505,9 @@ public class NameUtil {
}
if (StringUtil.toLowerCase(name.charAt(nameIndex)) != StringUtil.toLowerCase(myPattern[patternIndex])) {
if (Character.isDigit(name.charAt(nameIndex))) {
return matchName(name, patternIndex, nameIndex + 1);
}
return null;
}
@@ -788,6 +788,8 @@ public class UIUtil {
public static void drawSearchMatch(Graphics2D g, int startX, int endX, int height, Color c1, Color c2) {
final boolean drawRound = endX - startX > 4;
final Composite oldComposite = g.getComposite();
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f));
g.setPaint(new GradientPaint(startX, 2, c1, startX, height - 5, c2));
g.fillRect(startX, 3, endX - startX, height - 5);
@@ -802,6 +804,8 @@ public class UIUtil {
g.drawLine(startX, 3, endX - 1, 3);
g.drawLine(startX, height - 3, endX - 1, height - 3);
}
g.setComposite(oldComposite);
}
public static void drawRectPickedOut(Graphics2D g, int x, int y, int w, int h) {
@@ -42,5 +42,6 @@ public interface DebuggerIcons {
Icon WATCHED_VALUE_ICON = IconLoader.getIcon("/debugger/watch.png");
Icon STACK_FRAME_ICON = IconLoader.getIcon("/debugger/stackFrame.png");
Icon CURRENT_THREAD_ICON = IconLoader.getIcon("/debugger/threadCurrent.png");
Icon SUSPENDED_THREAD_ICON = IconLoader.getIcon("/debugger/threadSuspended.png");
}
@@ -55,7 +55,8 @@ archaic.system.property.accessors.replace.parse.quickfix=Replace with parse meth
archaic.system.property.accessors.replace.standard.quickfix=Replace with standard property access
equals.called.on.array.display.name='equals()' called on array type
equals.called.on.array.problem.descriptor=<code>#ref()</code> between arrays should probably be 'Arrays.equals()' #loc
equals.called.on.array.replace.quickfix=Replace with 'Arrays.equals()'
replace.with.arrays.equals=Replace with 'Arrays.equals()'
replace.with.arrays.deep.equals=Replace with 'Arrays.deepEquals()'
assignment.to.null.display.name=Assignment to 'null'
assignment.to.null.problem.descriptor=Assignment of variable <code>#ref</code> to null #loc
assignment.to.static.field.from.instance.method.display.name=Assignment to static field from instance method
@@ -887,7 +888,7 @@ nested.switch.statement.problem.descriptor=Nested <code>#ref</code> statement #l
chained.method.call.problem.descriptor=Chained method call <code>#ref()</code> #loc
nested.method.call.problem.descriptor=Nested method call <code>#ref()</code> #loc
octal.literal.problem.descriptor=Octal integer <code>#ref</code> #loc
implicit.call.to.super.problem.descriptor=Implicit call to super() <code>#ref</code> #loc
implicit.call.to.super.problem.descriptor=Implicit call to 'super()' #loc
negated.if.else.problem.descriptor=<code>#ref</code> statement with negated condition #loc
negated.conditional.problem.descriptor=Conditional expression with negated condition #loc
confusing.else.problem.descriptor=<code>#ref</code> branch may be unwrapped, as the 'if' branch never completes #loc
@@ -1346,7 +1347,7 @@ flip.comparison.quickfix=Flip comparison
control.flow.statement.without.braces.add.quickfix=Add braces
extends.object.remove.quickfix=Remove redundant 'extends Object'
implicit.call.to.super.ignore.option=Ignore for direct subclasses of java.lang.Object
implicit.call.to.super.make.explicit.quickfix=Make construction of super() explicit
implicit.call.to.super.make.explicit.quickfix=Make call to 'super()' explicit
missorted.modifiers.require.option=Require annotations to be sorted before keywords
missorted.modifiers.sort.quickfix=Sort modifiers
nested.method.call.ignore.option=Ignore nested method calls in field initializers
@@ -1598,7 +1599,7 @@ collection.contains.url.problem.decriptor={0} <code>#ref</code> may contain URL
collection.contains.url.display.name=Map or Set may contain java.net.URL objects
implicit.array.to.string.problem.descriptor=Implicit call to method 'toString()' on array <code>#ref</code> #loc
implicit.array.to.string.method.call.problem.descriptor=Implicit call to method 'toString()' on array returned by <code>#ref</code> call #loc
implicit.array.to.string.display.name=Implicit call to array '.toString()'
implicit.array.to.string.display.name=Call to array '.toString()'
implicit.array.to.string.quickfix=Wrap with ''{0}'' expression
suspicious.indent.after.control.statement.problem.descriptor=<code>#ref</code> statement has suspicious indentation #loc
suspicious.indent.after.control.statement.display.name=Suspicious indentation after control statement without braces
@@ -1867,3 +1868,5 @@ html.tag.can.be.javadoc.tag.quickfix=Replace with '{@code ...}'
try.finally.can.be.try.with.resources.display.name='try finally' replaceable with 'try' with resources
try.finally.can.be.try.with.resources.problem.descriptor=<code>#ref</code> can use automatic resource management
try.finally.can.be.try.with.resources.quickfix=Replace with 'try' with resources
array.comparison.display.name=Array comparison using '==', instead of 'Arrays.equals()'
array.comparison.problem.descriptor=Array objects are compared using <code>#ref</code>, not 'Arrays.equals()' #loc
@@ -516,6 +516,7 @@ public class InspectionGadgetsPlugin implements ApplicationComponent,
private void registerBugInspections() {
m_inspectionClasses.add(ArchaicSystemPropertyAccessInspection.class);
m_inspectionClasses.add(ArrayEqualityInspection.class);
m_inspectionClasses.add(ArrayEqualsInspection.class);
m_inspectionClasses.add(AssertWithSideEffectsInspection.class);
m_inspectionClasses.add(ConstantAssertConditionInspection.class);
@@ -0,0 +1,150 @@
/*
* Copyright 2011 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.bugs;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.psiutils.ComparisonUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class ArrayEqualityInspection extends BaseInspection {
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"array.comparison.display.name");
}
@Override
@NotNull
public String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message(
"array.comparison.problem.descriptor");
}
@Override
public InspectionGadgetsFix buildFix(Object... infos) {
final PsiArrayType type = (PsiArrayType) infos[0];
final PsiType componentType = type.getComponentType();
if (componentType instanceof PsiArrayType) {
return new ArrayEqualityFix(true);
}
return new ArrayEqualityFix(false);
}
private static class ArrayEqualityFix extends InspectionGadgetsFix {
private final boolean deepEquals;
public ArrayEqualityFix(boolean deepEquals) {
this.deepEquals = deepEquals;
}
@NotNull
@Override
public String getName() {
if (deepEquals) {
return InspectionGadgetsBundle.message(
"replace.with.arrays.deep.equals");
} else {
return InspectionGadgetsBundle.message(
"replace.with.arrays.equals");
}
}
@Override
protected void doFix(Project project, ProblemDescriptor descriptor)
throws IncorrectOperationException {
final PsiElement element = descriptor.getPsiElement();
final PsiElement parent = element.getParent();
if (!(parent instanceof PsiBinaryExpression)) {
return;
}
final PsiBinaryExpression binaryExpression =
(PsiBinaryExpression) parent;
final IElementType tokenType =
binaryExpression.getOperationTokenType();
@NonNls final StringBuilder newExpressionText = new StringBuilder();
if (JavaTokenType.NE.equals(tokenType)) {
newExpressionText.append('!');
} else if (!JavaTokenType.EQEQ.equals(tokenType)) {
return;
}
if (deepEquals) {
newExpressionText.append("java.util.Arrays.deepEquals(");
} else {
newExpressionText.append("java.util.Arrays.equals(");
}
newExpressionText.append(binaryExpression.getLOperand().getText());
newExpressionText.append(',');
final PsiExpression rhs = binaryExpression.getROperand();
if (rhs == null) {
return;
}
newExpressionText.append(rhs.getText());
newExpressionText.append(')');
replaceExpressionAndShorten(binaryExpression,
newExpressionText.toString());
}
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new ArrayEqualityVisitor();
}
private static class ArrayEqualityVisitor extends BaseInspectionVisitor {
@Override public void visitBinaryExpression(
@NotNull PsiBinaryExpression expression) {
super.visitBinaryExpression(expression);
final PsiExpression rhs = expression.getROperand();
if (rhs == null) {
return;
}
if (!ComparisonUtils.isEqualityComparison(expression)) {
return;
}
final PsiExpression lhs = expression.getLOperand();
final PsiType lhsType = lhs.getType();
if (!(lhsType instanceof PsiArrayType)) {
return;
}
if (!(rhs.getType() instanceof PsiArrayType)) {
return;
}
final String lhsText = lhs.getText();
if (PsiKeyword.NULL.equals(lhsText)) {
return;
}
final String rhsText = rhs.getText();
if (PsiKeyword.NULL.equals(rhsText)) {
return;
}
final PsiJavaToken sign = expression.getOperationSign();
registerError(sign, lhsType);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2008 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2011 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.
@@ -29,34 +29,57 @@ import org.jetbrains.annotations.NotNull;
public class ArrayEqualsInspection extends BaseInspection {
@Override
@NotNull
public String getDisplayName(){
return InspectionGadgetsBundle.message(
"equals.called.on.array.display.name");
}
@Override
@NotNull
public String buildErrorString(Object... infos){
return InspectionGadgetsBundle.message(
"equals.called.on.array.problem.descriptor");
}
@Override
public boolean isEnabledByDefault() {
return true;
}
@Override
public InspectionGadgetsFix buildFix(Object... infos){
return new ArrayEqualsFix();
final PsiArrayType type = (PsiArrayType)infos[0];
if (type != null) {
final PsiType componentType = type.getComponentType();
if (componentType instanceof PsiArrayType) {
return new ArrayEqualsFix(true);
}
}
return new ArrayEqualsFix(false);
}
private static class ArrayEqualsFix extends InspectionGadgetsFix{
@NotNull
public String getName(){
return InspectionGadgetsBundle.message(
"equals.called.on.array.replace.quickfix");
private final boolean deepEquals;
public ArrayEqualsFix(boolean deepEquals) {
this.deepEquals = deepEquals;
}
@NotNull
public String getName(){
if (deepEquals) {
return InspectionGadgetsBundle.message(
"replace.with.arrays.deep.equals");
} else {
return InspectionGadgetsBundle.message(
"replace.with.arrays.equals");
}
}
@Override
public void doFix(Project project, ProblemDescriptor descriptor)
throws IncorrectOperationException{
final PsiIdentifier name =
@@ -71,15 +94,23 @@ public class ArrayEqualsInspection extends BaseInspection {
final String qualifierText = qualifier.getText();
assert call != null;
final PsiExpressionList argumentList = call.getArgumentList();
final PsiExpression[] args = argumentList.getExpressions();
final String argText = args[0].getText();
@NonNls final String newExpressionText =
"java.util.Arrays.equals(" + qualifierText + ", " +
argText + ')';
replaceExpressionAndShorten(call, newExpressionText);
final PsiExpression[] arguments = argumentList.getExpressions();
final String argumentText = arguments[0].getText();
@NonNls final StringBuilder newExpressionText = new StringBuilder();
if (deepEquals) {
newExpressionText.append("java.util.Arrays.deepEquals(");
} else {
newExpressionText.append("java.util.Arrays.equals(");
}
newExpressionText.append(qualifierText);
newExpressionText.append(", ");
newExpressionText.append(argumentText);
newExpressionText.append(')');
replaceExpressionAndShorten(call, newExpressionText.toString());
}
}
@Override
public BaseInspectionVisitor buildVisitor(){
return new ArrayEqualsVisitor();
}
@@ -95,16 +126,16 @@ public class ArrayEqualsInspection extends BaseInspection {
final PsiReferenceExpression methodExpression =
expression.getMethodExpression();
final PsiExpressionList argumentList = expression.getArgumentList();
final PsiExpression[] args = argumentList.getExpressions();
if (args.length == 0) {
final PsiExpression[] arguments = argumentList.getExpressions();
if (arguments.length == 0) {
return;
}
final PsiExpression arg = args[0];
if(arg == null){
final PsiExpression argument = arguments[0];
if(argument == null){
return;
}
final PsiType argType = arg.getType();
if(!(argType instanceof PsiArrayType)){
final PsiType argumentType = argument.getType();
if(!(argumentType instanceof PsiArrayType)){
return;
}
final PsiExpression qualifier =
@@ -116,7 +147,7 @@ public class ArrayEqualsInspection extends BaseInspection {
if(!(qualifierType instanceof PsiArrayType)){
return;
}
registerMethodCallError(expression);
registerMethodCallError(expression, qualifierType);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2010 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2011 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.
@@ -48,7 +48,7 @@ public class NumberEqualityInspection extends BaseInspection {
@Override
public BaseInspectionVisitor buildVisitor() {
return new ObjectEqualityVisitor();
return new NumberEqualityVisitor();
}
@Override
@@ -56,32 +56,26 @@ public class NumberEqualityInspection extends BaseInspection {
return new EqualityToEqualsFix();
}
private static class ObjectEqualityVisitor extends BaseInspectionVisitor {
private static class NumberEqualityVisitor extends BaseInspectionVisitor {
@Override public void visitBinaryExpression(
@NotNull PsiBinaryExpression expression) {
super.visitBinaryExpression(expression);
if(!(expression.getROperand() != null)){
final PsiExpression rhs = expression.getROperand();
if (rhs == null) {
return;
}
if (!ComparisonUtils.isEqualityComparison(expression)) {
return;
}
final PsiExpression lhs = expression.getLOperand();
if (!hasNumberType(lhs)) {
return;
}
final PsiExpression rhs = expression.getROperand();
if (!hasNumberType(rhs)) {
if (!hasNumberType(lhs) || !hasNumberType(rhs)) {
return;
}
final String lhsText = lhs.getText();
if (PsiKeyword.NULL.equals(lhsText)) {
return;
}
if (rhs == null) {
return;
}
final String rhsText = rhs.getText();
if (PsiKeyword.NULL.equals(rhsText)) {
return;
@@ -90,8 +84,8 @@ public class NumberEqualityInspection extends BaseInspection {
registerError(sign);
}
private static boolean hasNumberType(PsiExpression lhs) {
return TypeUtils.expressionHasTypeOrSubtype(lhs,
private static boolean hasNumberType(PsiExpression expression) {
return TypeUtils.expressionHasTypeOrSubtype(expression,
CommonClassNames.JAVA_LANG_NUMBER);
}
}
@@ -0,0 +1,8 @@
<html>
<body>
This inspection reports any use of <b>==</b> to test for Array equality,
rather than the <b>"java.util.Arrays.equals()"</b> method.
<p>
<small>New in 10.5, Powered by InspectionGadgets</small>
</body>
</html>
@@ -43,6 +43,7 @@ import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
import org.intellij.plugins.intelliLang.inject.config.InjectionPlace;
import org.intellij.plugins.intelliLang.util.AnnotationUtilEx;
import org.intellij.plugins.intelliLang.util.ContextComputationProcessor;
import org.intellij.plugins.intelliLang.util.PsiUtilEx;
import org.jetbrains.annotations.NotNull;
import java.util.*;
@@ -117,6 +118,14 @@ public class ConcatenationInjector implements ConcatenationAwareInjector {
public void getLanguagesToInject(@NotNull final MultiHostRegistrar registrar, @NotNull PsiElement... operands) {
if (operands.length == 0) return;
boolean hasLiteral = false;
for (PsiElement operand : operands) {
if (PsiUtilEx.isStringOrCharacterLiteral(operand)) {
hasLiteral = true;
break;
}
}
if (!hasLiteral) return;
final PsiFile containingFile = operands[0].getContainingFile();
new InjectionProcessor(myConfiguration, operands) {
@Override
@@ -57,9 +57,9 @@ convert.integer.to.hex.intention.name=Convert to hex
convert.integer.to.hex.intention.family.name=Convert to Hexadecimal
convert.integer.to.binary.intention.name=Convert to binary
convert.integer.to.binary.intention.family.name=Convert to Binary
convert.to.engineering.notation.intention.name=Convert to Engineering notation
convert.to.engineering.notation.intention.family.name=Convert to Engineering notation
convert.to.plain.intention.name=Convert to Plain
convert.to.engineering.notation.intention.name=Convert to engineering notation
convert.to.engineering.notation.intention.family.name=Convert to Engineering Notation
convert.to.plain.intention.name=Convert to plain
convert.to.plain.intention.family.name=Convert to Plain
string.to.char.intention.name=Replace string literal with character
string.to.char.intention.family.name=Replace String with Char
@@ -15,48 +15,31 @@
*/
package com.siyeh.ipp.integer;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiExpression;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.ipp.base.Intention;
import com.intellij.psi.PsiType;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
/**
* @author Konstantin Bulenkov
* todo: actually it's a scientific notation, not an engineering one.
*/
public class ConvertToEngineeringNotationIntention extends Intention {
public class ConvertToEngineeringNotationIntention extends ConvertNumberIntentionBase {
private static final DecimalFormat FORMAT = new DecimalFormat("0.0#############E00", new DecimalFormatSymbols(Locale.US));
private static final DecimalFormat FORMAT =
new DecimalFormat("0.00000000000000E00");
private static final ConvertToEngineeringNotationPredicate PREDICATE =
new ConvertToEngineeringNotationPredicate();
@Override
protected String convertValue(final Number value, final PsiType type, final boolean negated) {
final double doubleValue = Double.parseDouble(value.toString()); // convert to double w/o adding parasitic digits
final String text = FORMAT.format(negated ? -doubleValue : doubleValue);
return PsiType.FLOAT.equals(type) ? text + "f" : text;
}
@Override
protected void processIntention(@NotNull PsiElement element)
throws IncorrectOperationException {
final String elementText = element.getText();
if (elementText.length() == 0) {
return;
}
final int lastIndex = elementText.length() - 1;
final char lastChar = elementText.charAt(lastIndex);
String text = FORMAT.format(Double.parseDouble(elementText)).replace(',', '.');
while (text.contains("0E") && !text.contains(".0E")) {
text = text.replace("0E", "E");
}
if (lastChar == 'f' || lastChar == 'F') {
replaceExpression(text + lastChar, (PsiExpression)element);
} else {
replaceExpression(text, (PsiExpression)element);
}
}
@NotNull
@Override
protected PsiElementPredicate getElementPredicate() {
return PREDICATE;
}
@NotNull
@Override
protected PsiElementPredicate getElementPredicate() {
return new ConvertToEngineeringNotationPredicate();
}
}
@@ -15,10 +15,7 @@
*/
package com.siyeh.ipp.integer;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiExpression;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.ipp.base.Intention;
import com.intellij.psi.PsiType;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
@@ -27,38 +24,18 @@ import java.math.BigDecimal;
/**
* @author Konstantin Bulenkov
*/
public class ConvertToPlainIntention extends Intention {
public class ConvertToPlainIntention extends ConvertNumberIntentionBase {
@Override
protected String convertValue(final Number value, final PsiType type, final boolean negated) {
String text = new BigDecimal(value.toString()).toPlainString();
if (negated) text = "-" + text;
if (PsiType.FLOAT.equals(type)) text += "f";
return text;
}
private static final ConvertToPlainPredicate PREDICATE =
new ConvertToPlainPredicate();
@Override
protected void processIntention(@NotNull PsiElement element)
throws IncorrectOperationException {
try {
final String elementText = element.getText();
if (elementText.length() == 0) {
return;
}
final int lastIndex = elementText.length() - 1;
final char lastChar = elementText.charAt(lastIndex);
if (lastChar == 'f' || lastChar == 'F') {
final BigDecimal bigDecimal =
new BigDecimal(elementText.substring(0, lastIndex));
replaceExpression(bigDecimal.toPlainString() + lastChar,
(PsiExpression) element);
} else {
final BigDecimal bigDecimal = new BigDecimal(elementText);
replaceExpression(bigDecimal.toPlainString(),
(PsiExpression) element);
}
} catch (Exception e) {//
}
}
@NotNull
@Override
protected PsiElementPredicate getElementPredicate() {
return PREDICATE;
}
@NotNull
@Override
protected PsiElementPredicate getElementPredicate() {
return new ConvertToPlainPredicate();
}
}
@@ -0,0 +1,3 @@
class C {
double x = <caret>1.23456789E03;
}
@@ -0,0 +1,3 @@
class C {
double x = 1234.56789;
}
@@ -0,0 +1,3 @@
class C {
float x = -<caret>12345.6789f;
}
@@ -0,0 +1,3 @@
class C {
float x = -1.2345679E04f;
}

Some files were not shown because too many files have changed in this diff Show More