Merge remote branch 'origin/master'

This commit is contained in:
irengrig
2012-11-13 17:00:22 +04:00
50 changed files with 827 additions and 344 deletions
+7 -5
View File
@@ -79,7 +79,7 @@ target('default': 'The default target') {
layoutAll([buildNumber: "IC-$snapshot",
system_selector: "IdeaIC${p("component.version.major")}",
tools_jar: true],
home, null, paths)
home, null, paths, true)
}
target('build-dist-jars' : 'Target to build jars from locally compiled classes') {
@@ -90,10 +90,10 @@ target('build-dist-jars' : 'Target to build jars from locally compiled classes')
layoutAll([buildNumber: "IC-$snapshot",
system_selector: "IdeaIC${p("component.version.major")}",
tools_jar: true],
home, null, paths)
home, null, paths)
}
def layoutAll(Map args, String home, String out, Paths _paths = null) {
def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps = false) {
Paths paths = _paths != null ? _paths : new Paths(out)
wireBuildDate(args.buildNumber, appInfoFile())
@@ -105,8 +105,10 @@ def layoutAll(Map args, String home, String out, Paths _paths = null) {
notifyArtifactBuilt(paths.artifacts_core)
layouts.layout_core_upsource(home, paths.artifacts_core_upsource)
notifyArtifactBuilt(paths.artifacts_core_upsource)
layouts.layout_jps(home, paths.artifacts_jps)
notifyArtifactBuilt(paths.artifacts_jps)
if (buildJps) {
layouts.layout_jps(home, paths.artifacts_jps)
notifyArtifactBuilt(paths.artifacts_jps)
}
layout(paths.distAll) {
dir("bin") {
@@ -15,9 +15,7 @@
*/
package com.intellij.platform.templates;
import com.intellij.ide.util.newProjectWizard.ProjectNameStep;
import com.intellij.ide.util.projectWizard.ModuleBuilder;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.ModuleTypeManager;
@@ -26,7 +24,6 @@ import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.platform.ProjectTemplate;
import com.intellij.ui.IdeBorderFactory;
import org.jdom.Document;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -47,19 +44,13 @@ public class ArchivedProjectTemplate implements ProjectTemplate {
private final String myDisplayName;
private final URL myArchivePath;
private final ModuleType myModuleType;
private final WizardContext myContext;
private final ProjectNameStep mySettingsStep;
public ArchivedProjectTemplate(String displayName,
URL archivePath,
WizardContext context) {
URL archivePath) {
myDisplayName = displayName;
myArchivePath = archivePath;
myContext = context;
myModuleType = computeModuleType(this);
mySettingsStep = new ProjectNameStep(context, null);
mySettingsStep.getComponent().setBorder(IdeBorderFactory.createEmptyBorder(0));
}
@NotNull
@@ -101,6 +101,11 @@ public class ArchivedTemplatesFactory implements ProjectTemplatesFactory {
return PathManager.getConfigPath() + "/resources/projectTemplates";
}
public static File getTemplateFile(String name) {
String configURL = getCustomTemplatesPath();
return new File(configURL + "/" + name + ".zip");
}
@NotNull
@Override
public String[] getGroups() {
@@ -122,7 +127,7 @@ public class ArchivedTemplatesFactory implements ProjectTemplatesFactory {
if (child.endsWith(ZIP)) {
URL templateUrl = new URL(url.toExternalForm() + "/" + child);
String name = child.substring(0, child.length() - ZIP.length()).replace('_', ' ');
templates.add(new ArchivedProjectTemplate(name, templateUrl, context));
templates.add(new ArchivedProjectTemplate(name, templateUrl));
}
}
}
@@ -18,21 +18,32 @@ package com.intellij.platform.templates;
import com.intellij.CommonBundle;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.StorageScheme;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.progress.PerformInBackgroundOption;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ex.ProjectEx;
import com.intellij.openapi.roots.ContentIterator;
import com.intellij.openapi.roots.FileIndex;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.io.ZipUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
@@ -44,9 +55,11 @@ import java.util.zip.ZipOutputStream;
*/
public class SaveProjectAsTemplateAction extends AnAction {
private static final Logger LOG = Logger.getInstance(SaveProjectAsTemplateAction.class);
@Override
public void actionPerformed(AnActionEvent e) {
Project project = getEventProject(e);
final Project project = getEventProject(e);
assert project != null;
StorageScheme scheme = ((ProjectEx)project).getStateStore().getStorageScheme();
if (scheme != StorageScheme.DIRECTORY_BASED) {
@@ -55,52 +68,127 @@ public class SaveProjectAsTemplateAction extends AnAction {
return;
}
VirtualFile descriptionFile = VfsUtil.findRelativeFile(project.getBaseDir(), ArchivedProjectTemplate.DESCRIPTION_PATH.split("/"));
SaveProjectAsTemplateDialog dialog = new SaveProjectAsTemplateDialog(project, descriptionFile);
if (dialog.showAndGet()) {
File file = dialog.getTemplateFile();
ZipOutputStream stream = null;
try {
file.getParentFile().mkdirs();
stream = new ZipOutputStream(new FileOutputStream(file));
final VirtualFile descriptionFile = getDescriptionFile(project);
final SaveProjectAsTemplateDialog dialog = new SaveProjectAsTemplateDialog(project, descriptionFile);
VirtualFile dir = getDirectoryToSave(project, dialog.getModuleToSave());
String description = dialog.getDescription();
if (descriptionFile == null) {
stream.putNextEntry(new ZipEntry(dir.getName() + "/" + ArchivedProjectTemplate.DESCRIPTION_PATH));
stream.write(description.getBytes());
stream.closeEntry();
if (dialog.showAndGet()) {
final Module moduleToSave = dialog.getModuleToSave();
final File file = dialog.getTemplateFile();
final String description = dialog.getDescription();
ProgressManager.getInstance().run(new Task.Backgroundable(project, "Saving Project as Template", true, PerformInBackgroundOption.DEAF) {
@Override
public void run(@NotNull final ProgressIndicator indicator) {
saveProject(project, file, moduleToSave, description, indicator);
}
else {
VfsUtil.saveText(descriptionFile, description);
@Override
public void onSuccess() {
Messages.showInfoMessage(FileUtil.getNameWithoutExtension(file) + " was successfully created.\n" +
"It's available now in Project Wizard", "Template Created");
}
ZipUtil.addDirToZipRecursively(stream, null, new File(dir.getPath()), dir.getName(), new FileFilter() {
@Override
public boolean accept(File pathname) {
if (!".idea".equals(pathname.getParent())) return true;
// todo filter out some garbage from .idea
return true;
}
}, null);
Messages.showInfoMessage(FileUtil.getNameWithoutExtension(file) + " was successfully created.\n" +
"It's available now in Project Wizard", "Template Created");
}
catch (IOException ex) {
Messages.showErrorDialog(project, ex.getMessage(), "Error");
}
finally {
StreamUtil.closeStream(stream);
}
@Override
public void onCancel() {
file.delete();
}
});
}
}
private static VirtualFile getDirectoryToSave(Project project, @Nullable String moduleName) {
if (moduleName == null) {
public static VirtualFile getDescriptionFile(Project project) {
return VfsUtil.findRelativeFile(ArchivedProjectTemplate.DESCRIPTION_PATH, project.getBaseDir());
}
public static void saveProject(final Project project,
final File zipFile,
Module moduleToSave,
final String description,
final ProgressIndicator indicator) {
indicator.setText("Saving project...");
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
project.save();
}
});
}
});
indicator.setText("Processing project files...");
ZipOutputStream stream = null;
try {
FileUtil.ensureExists(zipFile.getParentFile());
stream = new ZipOutputStream(new FileOutputStream(zipFile));
final VirtualFile dir = getDirectoryToSave(project, moduleToSave);
final VirtualFile descriptionFile = getDescriptionFile(project);
if (descriptionFile == null) {
stream.putNextEntry(new ZipEntry(dir.getName() + "/" + ArchivedProjectTemplate.DESCRIPTION_PATH));
stream.write(description.getBytes());
stream.closeEntry();
}
else {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
public void run() {
try {
VfsUtil.saveText(descriptionFile, description);
}
catch (IOException e) {
LOG.error(e);
}
}
});
}
FileIndex index = moduleToSave == null
? ProjectRootManager.getInstance(project).getFileIndex()
: ModuleRootManager.getInstance(moduleToSave).getFileIndex();
final ZipOutputStream finalStream = stream;
index.iterateContent(new ContentIterator() {
@Override
public boolean processFile(VirtualFile file) {
if (!file.isDirectory()) {
indicator.setText2(file.getName());
try {
String relativePath = VfsUtilCore.getRelativePath(file, dir, '/');
if (relativePath == null) {
throw new RuntimeException("Can't find relative path for " + file);
}
ZipUtil.addFileToZip(finalStream, new File(file.getPath()), dir.getName() + "/" + relativePath, null, null);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
indicator.checkCanceled();
// if (!".idea".equals(fileName.getParent())) return true;
// todo filter out some garbage from .idea
return true;
}
});
}
catch (Exception ex) {
LOG.error(ex);
UIUtil.invokeLaterIfNeeded(new Runnable() {
public void run() {
Messages.showErrorDialog(project, "Can't save project as template", "Internal Error");
}
});
}
finally {
StreamUtil.closeStream(stream);
}
}
private static VirtualFile getDirectoryToSave(Project project, @Nullable Module module) {
if (module == null) {
return project.getBaseDir();
}
else {
Module module = ModuleManager.getInstance(project).findModuleByName(moduleName);
assert module != null : "Can't find module " + moduleName;
VirtualFile moduleFile = module.getModuleFile();
assert moduleFile != null;
return moduleFile.getParent();
@@ -45,6 +45,7 @@ import java.util.List;
public class SaveProjectAsTemplateDialog extends DialogWrapper {
private static final String WHOLE_PROJECT = "<whole project>";
@NotNull private final Project myProject;
private JPanel myPanel;
private JTextField myName;
private EditorTextField myDescription;
@@ -53,6 +54,7 @@ public class SaveProjectAsTemplateDialog extends DialogWrapper {
protected SaveProjectAsTemplateDialog(@NotNull Project project, @Nullable VirtualFile descriptionFile) {
super(project);
myProject = project;
setTitle("Save Project As Template");
Module[] modules = ModuleManager.getInstance(project).getModules();
@@ -113,8 +115,7 @@ public class SaveProjectAsTemplateDialog extends DialogWrapper {
File getTemplateFile() {
String name = myName.getText();
String configURL = ArchivedTemplatesFactory.getCustomTemplatesPath();
return new File(configURL + "/" + name + ".zip");
return ArchivedTemplatesFactory.getTemplateFile(name);
}
String getDescription() {
@@ -122,10 +123,10 @@ public class SaveProjectAsTemplateDialog extends DialogWrapper {
}
@Nullable
String getModuleToSave() {
Module getModuleToSave() {
String item = (String)myModuleCombo.getSelectedItem();
if (item == null || item.equals(WHOLE_PROJECT)) return null;
return item;
return ModuleManager.getInstance(myProject).findModuleByName(item);
}
private final static Logger LOG = Logger.getInstance(SaveProjectAsTemplateDialog.class);
@@ -25,6 +25,7 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@@ -39,25 +40,26 @@ public class ExcludeCompilerOutputPolicy implements DirectoryIndexExcludePolicy
}
@Override
public boolean isExcludeRoot(final VirtualFile f) {
public boolean isExcludeRoot(final VirtualFile file) {
CompilerProjectExtension compilerProjectExtension = CompilerProjectExtension.getInstance(myProject);
if (isEqualWithFileOrUrl(f, compilerProjectExtension.getCompilerOutput(), compilerProjectExtension.getCompilerOutputUrl())) return true;
if (isEqualWithFileOrUrl(file, compilerProjectExtension.getCompilerOutput(), compilerProjectExtension.getCompilerOutputUrl())) return true;
for (Module m : ModuleManager.getInstance(myProject).getModules()) {
CompilerModuleExtension rm = CompilerModuleExtension.getInstance(m);
if (isEqualWithFileOrUrl(f, rm.getCompilerOutputPath(), rm.getCompilerOutputUrl())) return true;
if (isEqualWithFileOrUrl(f, rm.getCompilerOutputPathForTests(), rm.getCompilerOutputUrlForTests())) return true;
if (isEqualWithFileOrUrl(file, rm.getCompilerOutputPath(), rm.getCompilerOutputUrl())) return true;
if (isEqualWithFileOrUrl(file, rm.getCompilerOutputPathForTests(), rm.getCompilerOutputUrlForTests())) return true;
}
return false;
}
@Override
public boolean isExcludeRootForModule(final Module module, final VirtualFile excludeRoot) {
public boolean isExcludeRootForModule(@NotNull final Module module, final VirtualFile excludeRoot) {
final CompilerModuleExtension compilerModuleExtension = CompilerModuleExtension.getInstance(module);
return Comparing.equal(compilerModuleExtension.getCompilerOutputPath(), excludeRoot) ||
Comparing.equal(compilerModuleExtension.getCompilerOutputPathForTests(), excludeRoot);
}
@NotNull
@Override
public VirtualFile[] getExcludeRootsForProject() {
VirtualFile outputPath = CompilerProjectExtension.getInstance(myProject).getCompilerOutput();
@@ -67,8 +69,9 @@ public class ExcludeCompilerOutputPolicy implements DirectoryIndexExcludePolicy
return VirtualFile.EMPTY_ARRAY;
}
@NotNull
@Override
public VirtualFilePointer[] getExcludeRootsForModule(final ModuleRootModel rootModel) {
public VirtualFilePointer[] getExcludeRootsForModule(@NotNull final ModuleRootModel rootModel) {
ArrayList<VirtualFilePointer> result = new ArrayList<VirtualFilePointer>();
final CompilerModuleExtension extension = rootModel.getModuleExtension(CompilerModuleExtension.class);
if (extension == null) {
@@ -87,12 +90,12 @@ public class ExcludeCompilerOutputPolicy implements DirectoryIndexExcludePolicy
return result.isEmpty() ? VirtualFilePointer.EMPTY_ARRAY : result.toArray(new VirtualFilePointer[result.size()]);
}
private static boolean isEqualWithFileOrUrl(VirtualFile f, VirtualFile fileToCompareWith, String url) {
private static boolean isEqualWithFileOrUrl(VirtualFile file, VirtualFile fileToCompareWith, String url) {
if (fileToCompareWith != null) {
if (Comparing.equal(fileToCompareWith, f)) return true;
if (Comparing.equal(fileToCompareWith, file)) return true;
}
else if (url != null) {
if (FileUtil.pathsEqual(url, f.getUrl())) return true;
if (FileUtil.pathsEqual(url, file.getUrl())) return true;
}
return false;
}
@@ -15,10 +15,14 @@
*/
package com.intellij.core;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.SuggestedNameInfo;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import org.intellij.lang.annotations.MagicConstant;
import org.jetbrains.annotations.NonNls;
@@ -26,6 +30,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.LinkedHashSet;
public class CoreJavaCodeStyleManager extends JavaCodeStyleManager {
@Override
@@ -96,16 +101,75 @@ public class CoreJavaCodeStyleManager extends JavaCodeStyleManager {
@Override
public String suggestUniqueVariableName(@NonNls String baseName, PsiElement place, boolean lookForward) {
return null;
int index = 0;
PsiElement scope = PsiTreeUtil.getNonStrictParentOfType(place, PsiStatement.class, PsiCodeBlock.class, PsiMethod.class);
NextName:
while (true) {
String name = baseName;
if (index > 0) {
name += index;
}
index++;
if (PsiUtil.isVariableNameUnique(name, place)) {
if (lookForward) {
final String name1 = name;
PsiElement run = scope;
while (run != null) {
class CancelException extends RuntimeException {
}
try {
run.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitAnonymousClass(final PsiAnonymousClass aClass) {
}
@Override public void visitVariable(PsiVariable variable) {
if (name1.equals(variable.getName())) {
throw new CancelException();
}
}
});
}
catch (CancelException e) {
continue NextName;
}
run = run.getNextSibling();
if (scope instanceof PsiMethod) {//do not check next member for param name conflict
break;
}
}
}
return name;
}
}
}
@NotNull
@Override
public SuggestedNameInfo suggestUniqueVariableName(@NotNull SuggestedNameInfo baseNameInfo,
public SuggestedNameInfo suggestUniqueVariableName(@NotNull final SuggestedNameInfo baseNameInfo,
PsiElement place,
boolean ignorePlaceName,
boolean lookForward) {
return SuggestedNameInfo.NULL_INFO;
final String[] names = baseNameInfo.names;
final LinkedHashSet<String> uniqueNames = new LinkedHashSet<String>(names.length);
for (String name : names) {
if (ignorePlaceName && place instanceof PsiNamedElement) {
final String placeName = ((PsiNamedElement)place).getName();
if (Comparing.strEqual(placeName, name)) {
uniqueNames.add(name);
continue;
}
}
uniqueNames.add(suggestUniqueVariableName(name, place, lookForward));
}
return new SuggestedNameInfo(ArrayUtil.toStringArray(uniqueNames)) {
@Override
public void nameChosen(String name) {
baseNameInfo.nameChosen(name);
}
};
}
@Override
@@ -266,7 +266,7 @@ public class ExpressionParser {
builder.advanceLexer();
final ReferenceParser.TypeInfo typeInfo =
myParser.getReferenceParser().parseTypeInfo(builder, ReferenceParser.EAT_LAST_DOT | ReferenceParser.WILDCARD);
myParser.getReferenceParser().parseTypeInfo(builder, ReferenceParser.EAT_LAST_DOT | ReferenceParser.WILDCARD | ReferenceParser.CONJUNCTIONS);
if (typeInfo == null || !expect(builder, JavaTokenType.RPARENTH)) {
typeCast.rollbackTo();
return parsePostfix(builder);
@@ -28,6 +28,8 @@ import org.jetbrains.annotations.Nullable;
import static com.intellij.lang.PsiBuilderUtil.expect;
import static com.intellij.lang.java.parser.JavaParserUtil.*;
import static com.intellij.util.BitUtil.isSet;
import static com.intellij.util.BitUtil.notSet;
import static com.intellij.util.BitUtil.set;
public class ReferenceParser {
public static final int EAT_LAST_DOT = 0x01;
@@ -35,6 +37,7 @@ public class ReferenceParser {
public static final int WILDCARD = 0x04;
public static final int DIAMONDS = 0x08;
public static final int DISJUNCTIONS = 0x10;
public static final int CONJUNCTIONS = 0x20;
public static class TypeInfo {
public boolean isPrimitive = false;
@@ -61,29 +64,32 @@ public class ReferenceParser {
@Nullable
public TypeInfo parseTypeInfo(final PsiBuilder builder, final int flags) {
final TypeInfo typeInfo = parseTypeInfo(builder, isSet(flags, EAT_LAST_DOT), isSet(flags, WILDCARD), false, isSet(flags, DIAMONDS),
isSet(flags, ELLIPSIS));
final TypeInfo typeInfo = parseTypeInfo(builder, flags, false);
if (typeInfo != null && isSet(flags, DISJUNCTIONS) && builder.getTokenType() == JavaTokenType.OR) {
typeInfo.marker = typeInfo.marker.precede();
if (typeInfo != null) {
assert notSet(flags, DISJUNCTIONS|CONJUNCTIONS) : "don't not set both flags simultaneously";
final IElementType operator = isSet(flags, DISJUNCTIONS) ? JavaTokenType.OR : isSet(flags, CONJUNCTIONS) ? JavaTokenType.AND : null;
while (builder.getTokenType() == JavaTokenType.OR) {
builder.advanceLexer();
if (builder.getTokenType() != JavaTokenType.IDENTIFIER) {
error(builder, JavaErrorMessages.message("expected.identifier"));
if (operator != null && builder.getTokenType() == operator) {
typeInfo.marker = typeInfo.marker.precede();
while (builder.getTokenType() == operator) {
builder.advanceLexer();
if (builder.getTokenType() != JavaTokenType.IDENTIFIER) {
error(builder, JavaErrorMessages.message("expected.identifier"));
}
parseTypeInfo(builder, flags, false);
}
parseTypeInfo(builder, isSet(flags, EAT_LAST_DOT), isSet(flags, WILDCARD), false, isSet(flags, DIAMONDS), isSet(flags, ELLIPSIS));
}
typeInfo.marker.done(JavaElementType.TYPE);
typeInfo.marker.done(JavaElementType.TYPE);
}
}
return typeInfo;
}
@Nullable
private TypeInfo parseTypeInfo(final PsiBuilder builder, final boolean eatLastDot, final boolean wildcard, final boolean badWildcard,
final boolean diamonds, final boolean ellipsis) {
private TypeInfo parseTypeInfo(final PsiBuilder builder, final int flags, final boolean badWildcard) {
if (builder.getTokenType() == null) return null;
final TypeInfo typeInfo = new TypeInfo();
@@ -96,14 +102,14 @@ public class ReferenceParser {
typeInfo.isPrimitive = true;
}
else if (tokenType == JavaTokenType.IDENTIFIER) {
parseJavaCodeReference(builder, eatLastDot, true, false, false, false, diamonds, typeInfo);
parseJavaCodeReference(builder, isSet(flags, EAT_LAST_DOT), true, false, false, false, isSet(flags, DIAMONDS), typeInfo);
}
else if ((wildcard || badWildcard) && tokenType == JavaTokenType.QUEST) {
else if ((isSet(flags, WILDCARD) || badWildcard) && tokenType == JavaTokenType.QUEST) {
type.drop();
typeInfo.marker = parseWildcardType(builder, wildcard);
typeInfo.marker = parseWildcardType(builder, isSet(flags, WILDCARD));
return typeInfo.marker != null ? typeInfo : null;
}
else if (diamonds && tokenType == JavaTokenType.GT) {
else if (isSet(flags, DIAMONDS) && tokenType == JavaTokenType.GT) {
emptyElement(builder, JavaElementType.DIAMOND_TYPE);
type.done(JavaElementType.TYPE);
typeInfo.marker = type;
@@ -133,7 +139,7 @@ public class ReferenceParser {
type = type.precede();
}
if (ellipsis && builder.getTokenType() == JavaTokenType.ELLIPSIS) {
if (isSet(flags, ELLIPSIS) && builder.getTokenType() == JavaTokenType.ELLIPSIS) {
type = type.precede();
builder.advanceLexer();
type.done(JavaElementType.TYPE);
@@ -263,9 +269,10 @@ public class ReferenceParser {
return false;
}
final int flags = set(set(EAT_LAST_DOT, WILDCARD, wildcard), DIAMONDS, diamonds);
boolean isOk = true;
while (true) {
if (parseTypeInfo(builder, true, wildcard, true, diamonds, false) == null) {
if (parseTypeInfo(builder, flags, true) == null) {
error(builder, JavaErrorMessages.message("expected.identifier"));
}
else {
@@ -1,18 +1,28 @@
PsiJavaFile:LambdaExpression12.java
PsiErrorElement:Unparsed tokens
PsiJavaToken:LT('<')
PsiIdentifier:T('T')
PsiJavaToken:GT('>')
PsiTypeCastExpression:(I1 & I2) () -> null
PsiJavaToken:LPARENTH('(')
PsiTypeElement:I1 & I2
PsiTypeElement:I1
PsiJavaCodeReferenceElement:I1
PsiIdentifier:I1('I1')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiJavaToken:AND('&')
PsiWhiteSpace(' ')
PsiTypeElement:I2
PsiJavaCodeReferenceElement:I2
PsiIdentifier:I2('I2')
PsiReferenceParameterList
<empty list>
PsiJavaToken:RPARENTH(')')
PsiWhiteSpace(' ')
PsiJavaToken:ARROW('->')
PsiWhiteSpace(' ')
PsiKeyword:new('new')
PsiWhiteSpace(' ')
PsiIdentifier:C('C')
PsiJavaToken:LT('<')
PsiIdentifier:T('T')
PsiJavaToken:GT('>')
PsiJavaToken:LPARENTH('(')
PsiJavaToken:RPARENTH(')')
PsiLambdaExpression:() -> null
PsiParameterList:()
PsiJavaToken:LPARENTH('(')
PsiJavaToken:RPARENTH(')')
PsiWhiteSpace(' ')
PsiJavaToken:ARROW('->')
PsiWhiteSpace(' ')
PsiLiteralExpression:null
PsiJavaToken:NULL_KEYWORD('null')
@@ -1,10 +1,29 @@
PsiJavaFile:LambdaExpression13.java
PsiErrorElement:Unparsed tokens
PsiJavaToken:LT('<')
PsiIdentifier:T('T')
PsiJavaToken:GT('>')
PsiIdentifier:t('t')
PsiTypeCastExpression:(I1 & I2) () -> {}
PsiJavaToken:LPARENTH('(')
PsiTypeElement:I1 & I2
PsiTypeElement:I1
PsiJavaCodeReferenceElement:I1
PsiIdentifier:I1('I1')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiJavaToken:AND('&')
PsiWhiteSpace(' ')
PsiTypeElement:I2
PsiJavaCodeReferenceElement:I2
PsiIdentifier:I2('I2')
PsiReferenceParameterList
<empty list>
PsiJavaToken:RPARENTH(')')
PsiWhiteSpace(' ')
PsiJavaToken:ARROW('->')
PsiWhiteSpace(' ')
PsiIdentifier:t('t')
PsiLambdaExpression:() -> {}
PsiParameterList:()
PsiJavaToken:LPARENTH('(')
PsiJavaToken:RPARENTH(')')
PsiWhiteSpace(' ')
PsiJavaToken:ARROW('->')
PsiWhiteSpace(' ')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiJavaToken:RBRACE('}')
@@ -134,15 +134,14 @@ public class ExpressionParserTest extends JavaParsingTestCase {
public void testLambdaExpression9() { doParserTest("(I)p -> null"); }
public void testLambdaExpression10() { doParserTest("(I)(p -> null)"); }
public void testLambdaExpression11() { doParserTest("() -> { }"); }
public void testLambdaExpression12() { doParserTest("<T>() -> new C<T>()"); } // these two expressions
public void testLambdaExpression13() { doParserTest("<T>t -> t"); } // should no longer be parsed
public void testLambdaExpression12() { doParserTest("(I1 & I2) () -> null"); }
public void testLambdaExpression13() { doParserTest("(I1 & I2) () -> {}"); }
public void testLambdaExpression14() { doParserTest("(String t) -> t"); }
public void testLambdaExpression15() { doParserTest("(int a, int b) -> a + b"); }
public void testLambdaExpression16() { doParserTest("(final int x) -> x"); }
public void testLambdaExpression17() { doParserTest("(String s -> s"); }
public void testLambdaExpression18() { doParserTest("(java.lang.String s, -> s"); }
public void testLambdaExpression19() { doParserTest("(@A T t) -> (null)"); }
public void testAmbiguousLambdaExpression() { doParserTest("f( (x) < y , z > (w) -> v )"); }
private void doParserTest(@NonNls final String text) {
@@ -112,6 +112,9 @@ public interface Project extends ComponentManager, AreaInstance {
@NonNls
String getLocation();
/**
* Should be invoked under WriteAction.
*/
void save();
boolean isOpen();
@@ -29,8 +29,8 @@ public class ArrangementConstants {
public static final DataKey<ArrangementMatchingRulesControl> MATCHING_RULES_CONTROL_KEY = DataKey.create("Arrangement.RuleEditor");
@NonNls public static final String ACTION_GROUP_RULE_EDITOR_CONTEXT_MENU = "Arrangement.RuleEditor.Context.Menu";
@NonNls public static final String ACTION_GROUP_MATCHING_RULES_CONTROL_TOOLBAR = "Arrangement.RuleEditor.ToolBar";
@NonNls public static final String ACTION_GROUP_MATCHING_RULES_CONTEXT_MENU = "Arrangement.Rule.Match.Control.Context.Menu";
@NonNls public static final String ACTION_GROUP_MATCHING_RULES_CONTROL_TOOLBAR = "Arrangement.Rule.Match.Control.ToolBar";
@NonNls public static final String RULE_EDITOR_PLACE = "Arrangement.RuleEditor.Place";
@NonNls public static final String MATCHING_RULES_CONTROL_TOOLBAR_PLACE = "Arrangement.Rule.Match.Control.ToolBar.Place";
@@ -48,8 +48,6 @@ public class ArrangementConstants {
public static final boolean LOG_RULE_MODIFICATION = Boolean.parseBoolean(System.getProperty("log.arrangement.rule.modification"));
public static final DataKey<Runnable> NEW_RULE_FUNCTION_KEY = DataKey.create("Arrangement.Rule.Function.New");
public static final DataKey<NotNullFunction<Boolean/* move up? */, Boolean/* is enabled */>> UPDATE_MOVE_RULE_FUNCTION_KEY
= DataKey.create("Arrangement.Rule.Function.Update.Move");
public static final DataKey<Consumer<Boolean/* move up? */>> MOVE_RULE_FUNCTION_KEY = DataKey.create("Arrangement.Rule.Function.Move");
@@ -34,6 +34,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Encapsulates various functionality related to showing arrangement nodes to end-users.
@@ -62,8 +63,8 @@ public class ArrangementNodeDisplayManager {
}
private void refreshMaxWidths() {
Map<ArrangementSettingType, Collection<?>> map = ArrangementConfigUtil.buildAvailableConditions(myFilter, null);
for (Map.Entry<ArrangementSettingType, Collection<?>> entry : map.entrySet()) {
Map<ArrangementSettingType, Set<?>> map = ArrangementConfigUtil.buildAvailableConditions(myFilter, null);
for (Map.Entry<ArrangementSettingType, Set<?>> entry : map.entrySet()) {
myMaxWidths.put(entry.getKey(), maxWidth(entry.getKey(), entry.getValue()));
}
}
@@ -16,10 +16,14 @@
package com.intellij.application.options.codeStyle.arrangement.action;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.application.options.codeStyle.arrangement.component.EmptyArrangementRuleComponent;
import com.intellij.application.options.codeStyle.arrangement.match.ArrangementMatchingRulesControl;
import com.intellij.application.options.codeStyle.arrangement.match.ArrangementMatchingRulesModel;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.project.DumbAware;
import gnu.trove.TIntArrayList;
/**
* @author Denis Zhdanov
@@ -34,9 +38,24 @@ public class AddArrangementRuleAction extends AnAction implements DumbAware {
@Override
public void actionPerformed(AnActionEvent e) {
Runnable function = ArrangementConstants.NEW_RULE_FUNCTION_KEY.getData(e.getDataContext());
if (function != null) {
function.run();
ArrangementMatchingRulesControl control = ArrangementConstants.MATCHING_RULES_CONTROL_KEY.getData(e.getDataContext());
if (control == null) {
return;
}
control.hideEditor();
TIntArrayList rows = control.getSelectedModelRows();
ArrangementMatchingRulesModel model = control.getModel();
int rowToEdit;
if (rows.size() == 1) {
rowToEdit = rows.get(0) + 1;
model.insertRow(rowToEdit, new Object[] { new EmptyArrangementRuleComponent(control.getRowHeight(rowToEdit)) });
}
else {
rowToEdit = model.getSize();
model.add(new EmptyArrangementRuleComponent(control.getRowHeight(rowToEdit)));
}
control.showEditor(rowToEdit);
control.getSelectionModel().setSelectionInterval(rowToEdit, rowToEdit);
}
}
@@ -15,11 +15,14 @@
*/
package com.intellij.application.options.codeStyle.arrangement.action;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.application.options.codeStyle.arrangement.match.ArrangementMatchingRulesControl;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Toggleable;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.project.DumbAware;
import gnu.trove.TIntArrayList;
/**
* @author Denis Zhdanov
@@ -31,9 +34,23 @@ public class EditArrangementRuleAction extends AnAction implements DumbAware, To
getTemplatePresentation().setText(ApplicationBundle.message("arrangement.action.rule.edit.text"));
getTemplatePresentation().setDescription(ApplicationBundle.message("arrangement.action.rule.edit.description"));
}
@Override
public void update(AnActionEvent e) {
ArrangementMatchingRulesControl control = ArrangementConstants.MATCHING_RULES_CONTROL_KEY.getData(e.getDataContext());
e.getPresentation().setEnabled(control != null && control.getSelectedModelRows().size() == 1);
}
@Override
public void actionPerformed(AnActionEvent e) {
// TODO den implement
ArrangementMatchingRulesControl control = ArrangementConstants.MATCHING_RULES_CONTROL_KEY.getData(e.getDataContext());
if (control == null) {
return;
}
TIntArrayList rows = control.getSelectedModelRows();
if (rows.size() != 1) {
return;
}
control.showEditor(rows.get(0));
}
}
@@ -62,11 +62,5 @@ public class RemoveArrangementRuleAction extends AnAction {
}
}
});
//int repaintMax = model.getSize() - 1;
//int min = rowsToRemove.get(rowsToRemove.size() - 1);
//if (repaintMax >= 0 && min <= repaintMax) {
// control.repaintRows(min, repaintMax, true);
//}
}
}
@@ -0,0 +1,53 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.application.options.codeStyle.arrangement.component;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.util.ui.GridBag;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
/**
* @author Denis Zhdanov
* @since 11/13/12 1:31 PM
*/
public class EmptyArrangementRuleComponent extends JPanel implements ArrangementRepresentationAware {
private final int myHeight;
public EmptyArrangementRuleComponent(int height) {
super(new GridBagLayout());
myHeight = height;
add(new JLabel(ApplicationBundle.message("arrangement.text.empty.rule")), new GridBag().anchor(GridBagConstraints.WEST));
setBackground(UIUtil.getDecoratedRowColor());
}
@NotNull
@Override
public JComponent getComponent() {
return this;
}
@Override
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
return new Dimension(size.width, myHeight);
}
}
@@ -20,6 +20,7 @@ import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDis
import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider;
import com.intellij.application.options.codeStyle.arrangement.component.ArrangementAtomMatchConditionComponent;
import com.intellij.application.options.codeStyle.arrangement.component.ArrangementMatchConditionComponent;
import com.intellij.application.options.codeStyle.arrangement.component.EmptyArrangementRuleComponent;
import com.intellij.application.options.codeStyle.arrangement.util.ArrangementConfigUtil;
import com.intellij.psi.codeStyle.arrangement.ArrangementConditionInfo;
import com.intellij.psi.codeStyle.arrangement.ArrangementUtil;
@@ -59,7 +60,7 @@ public class ArrangementMatchingRuleEditor extends JPanel {
@NotNull private final Map<Object, ArrangementAtomMatchConditionComponent> myComponents =
new HashMap<Object, ArrangementAtomMatchConditionComponent>();
@NotNull private final ArrangementMatchingRulesControl myControl;
@NotNull private final ArrangementStandardSettingsAware myFilter;
@NotNull private final ArrangementColorsProvider myColorsProvider;
@@ -89,16 +90,16 @@ public class ArrangementMatchingRuleEditor extends JPanel {
setLayout(new GridBagLayout());
setBorder(IdeBorderFactory.createEmptyBorder(5));
Map<ArrangementSettingType, Collection<?>> supportedSettings = ArrangementConfigUtil.buildAvailableConditions(myFilter, null);
Map<ArrangementSettingType, Set<?>> supportedSettings = ArrangementConfigUtil.buildAvailableConditions(myFilter, null);
addRowIfPossible(ArrangementSettingType.TYPE, supportedSettings, displayManager);
addRowIfPossible(ArrangementSettingType.MODIFIER, supportedSettings, displayManager);
}
private void addRowIfPossible(@NotNull ArrangementSettingType key,
@NotNull Map<ArrangementSettingType, Collection<?>> supportedSettings,
@NotNull Map<ArrangementSettingType, Set<?>> supportedSettings,
@NotNull ArrangementNodeDisplayManager manager)
{
Collection<?> values = supportedSettings.get(key);
Set<?> values = supportedSettings.get(key);
if (values == null || values.isEmpty()) {
return;
}
@@ -129,8 +130,14 @@ public class ArrangementMatchingRuleEditor extends JPanel {
* <code>'-1'</code> as an indication that no settings should be active
*/
public void updateState(int row) {
myRow = row;
myConditionInfo = null;
updateState(row, true);
}
private void updateState(int row, boolean newModel) {
if (newModel) {
myRow = row;
myConditionInfo = null;
}
// Reset state.
for (ArrangementAtomMatchConditionComponent component : myComponents.values()) {
@@ -145,15 +152,23 @@ public class ArrangementMatchingRuleEditor extends JPanel {
}
Object element = model.getElementAt(row);
if (element instanceof EmptyArrangementRuleComponent) {
for (ArrangementAtomMatchConditionComponent component : myComponents.values()) {
ArrangementAtomMatchCondition condition = component.getMatchCondition();
Map<ArrangementSettingType, Set<?>> map = ArrangementConfigUtil.buildAvailableConditions(myFilter, condition);
component.setEnabled(map.get(condition.getType()).contains(condition.getValue()));
}
myConditionInfo = new ArrangementConditionInfo();
return;
}
if (!(element instanceof StdArrangementMatchRule)) {
myRow = -1;
return;
}
ArrangementMatchCondition condition = ((StdArrangementMatchRule)element).getMatcher().getCondition();
myConditionInfo = ArrangementUtil.extractConditions(condition);
Map<ArrangementSettingType, Collection<?>> available = ArrangementConfigUtil.buildAvailableConditions(myFilter, condition);
Map<ArrangementSettingType, Set<?>> available = ArrangementConfigUtil.buildAvailableConditions(myFilter, condition);
for (Collection<?> ids : available.values()) {
for (Object id : ids) {
ArrangementAtomMatchConditionComponent component = myComponents.get(id);
@@ -169,9 +184,12 @@ public class ArrangementMatchingRuleEditor extends JPanel {
private void updateState() {
assert myConditionInfo != null;
ArrangementMatchCondition newCondition = myConditionInfo.buildCondition();
myControl.getModel().set(myRow, newCondition == null ? null : new StdArrangementMatchRule(new StdArrangementEntryMatcher(newCondition)));
Object modelValue = newCondition == null
? new EmptyArrangementRuleComponent(myControl.getRowHeight(myRow))
: new StdArrangementMatchRule(new StdArrangementEntryMatcher(newCondition));
myControl.getModel().set(myRow, modelValue);
myControl.repaintRows(myRow, myRow, true);
updateState(myRow);
updateState(myRow, false);
}
public void applyAvailableWidth(int width) {
@@ -204,7 +222,8 @@ public class ArrangementMatchingRuleEditor extends JPanel {
component.setSelected(!remove);
repaintComponent(component);
if (remove) {
myConditionInfo.removeCondition(chosenCondition);
myConditionInfo.removeCondition(chosenCondition.getValue());
ensureConsistency();
updateState();
return;
}
@@ -239,6 +258,32 @@ public class ArrangementMatchingRuleEditor extends JPanel {
updateState();
}
private void ensureConsistency() {
if (myConditionInfo == null) {
return;
}
ArrangementMatchCondition condition = myConditionInfo.buildCondition();
Map<ArrangementSettingType, Set<?>> map = ArrangementConfigUtil.buildAvailableConditions(myFilter, condition);
for (ArrangementAtomMatchConditionComponent c : myComponents.values()) {
Object v = c.getMatchCondition().getValue();
if (!myConditionInfo.hasCondition(v)) {
continue;
}
boolean remain = false;
for (Set<?> s : map.values()) {
if (s.contains(v)) {
remain = true;
break;
}
}
if (!remain) {
myConditionInfo.removeCondition(v);
ensureConsistency();
return;
}
}
}
@Nullable
private ArrangementAtomMatchConditionComponent getNodeComponentAt(@NotNull Point screenPoint) {
for (ArrangementAtomMatchConditionComponent component : myComponents.values()) {
@@ -79,6 +79,7 @@ public class ArrangementMatchingRulesControl extends JBTable {
setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
setShowColumns(false);
setShowGrid(false);
putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
myEditor = new ArrangementMatchingRuleEditor(settingsFilter, colorsProvider, displayManager, this);
addMouseMotionListener(new MouseAdapter() {
@Override
@@ -255,7 +256,11 @@ public class ArrangementMatchingRulesControl extends JBTable {
}
mySkipSelectionChange = true;
try {
getModel().removeRow(myEditorRow);
ArrangementMatchingRulesModel model = getModel();
model.removeRow(myEditorRow);
if (myEditorRow > 0 && model.getElementAt(myEditorRow - 1) instanceof EmptyArrangementRuleComponent) {
model.removeRow(myEditorRow - 1);
}
}
finally {
mySkipSelectionChange = false;
@@ -298,7 +303,6 @@ public class ArrangementMatchingRulesControl extends JBTable {
}
editor.applyAvailableWidth(width);
myEditor.updateState(rowToEdit);
myComponents.shiftKeys(myEditorRow, 1);
mySkipSelectionChange = true;
try {
getModel().insertRow(myEditorRow, new Object[]{editor});
@@ -411,14 +415,14 @@ public class ArrangementMatchingRulesControl extends JBTable {
}
}
private static class MyEditor extends AbstractTableCellEditor {
private class MyEditor extends AbstractTableCellEditor {
@Nullable private Object myValue;
private int myRow;
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
if (value instanceof ArrangementEditorAware) {
myValue = value;
myRow = row;
return ((ArrangementEditorAware)value).getComponent();
}
return null;
@@ -426,14 +430,7 @@ public class ArrangementMatchingRulesControl extends JBTable {
@Override
public Object getCellEditorValue() {
return myValue;
}
@Override
public boolean stopCellEditing() {
boolean result = super.stopCellEditing();
myValue = null;
return result;
return myRow < getModel().getSize() ? getModel().getElementAt(myRow) : null;
}
}
@@ -19,6 +19,7 @@ import com.intellij.application.options.codeStyle.arrangement.ArrangementConstan
import com.intellij.application.options.codeStyle.arrangement.ArrangementNodeDisplayManager;
import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider;
import com.intellij.application.options.codeStyle.arrangement.util.TitleWithToolbar;
import com.intellij.ide.ui.customization.CustomizationUtil;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
@@ -46,12 +47,7 @@ public class ArrangementMatchingRulesPanel extends JPanel implements DataProvide
@NotNull ArrangementStandardSettingsAware settingsFilter)
{
super(new GridBagLayout());
TitleWithToolbar top = new TitleWithToolbar(
ApplicationBundle.message("arrangement.settings.section.match"),
ArrangementConstants.ACTION_GROUP_MATCHING_RULES_CONTROL_TOOLBAR,
ArrangementConstants.MATCHING_RULES_CONTROL_TOOLBAR_PLACE
);
JBScrollPane scrollPane = new JBScrollPane();
final JViewport viewport = scrollPane.getViewport();
ArrangementMatchingRulesControl.RepresentationCallback callback = new ArrangementMatchingRulesControl.RepresentationCallback() {
@@ -75,7 +71,16 @@ public class ArrangementMatchingRulesPanel extends JPanel implements DataProvide
};
myControl = new ArrangementMatchingRulesControl(displayManager, colorsProvider, settingsFilter, callback);
scrollPane.setViewportView(myControl);
CustomizationUtil.installPopupHandler(
myControl, ArrangementConstants.ACTION_GROUP_MATCHING_RULES_CONTEXT_MENU, ArrangementConstants.RULE_EDITOR_PLACE
);
TitleWithToolbar top = new TitleWithToolbar(
ApplicationBundle.message("arrangement.settings.section.match"),
ArrangementConstants.ACTION_GROUP_MATCHING_RULES_CONTROL_TOOLBAR,
ArrangementConstants.MATCHING_RULES_CONTROL_TOOLBAR_PLACE,
myControl
);
add(top, new GridBag().coverLine().fillCellHorizontally().weightx(1));
add(scrollPane, new GridBag().fillCell().weightx(1).weighty(1));
}
@@ -25,8 +25,10 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.util.List;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Contains various utility methods to be used during showing arrangement settings.
@@ -42,17 +44,17 @@ public class ArrangementConfigUtil {
}
/**
* Allows to answer what new settings are available for a particular match condition.
* Allows to answer what settings are available for a particular match condition.
*
* @param filter filter to use
* @param condition object that encapsulates information about current arrangement matcher settings
* @return map which contains information on what new new settings are available at the current situation
* @return map which contains information on what settings are available at the current situation
*/
@NotNull
public static Map<ArrangementSettingType, Collection<?>> buildAvailableConditions(@NotNull ArrangementStandardSettingsAware filter,
public static Map<ArrangementSettingType, Set<?>> buildAvailableConditions(@NotNull ArrangementStandardSettingsAware filter,
@Nullable ArrangementMatchCondition condition)
{
Map<ArrangementSettingType, Collection<?>> result = new EnumMap<ArrangementSettingType, Collection<?>>(ArrangementSettingType.class);
Map<ArrangementSettingType, Set<?>> result = new EnumMap<ArrangementSettingType, Set<?>>(ArrangementSettingType.class);
processData(filter, condition, result, ArrangementSettingType.TYPE, ArrangementEntryType.values());
processData(filter, condition, result, ArrangementSettingType.MODIFIER, ArrangementModifier.values());
return result;
@@ -60,17 +62,17 @@ public class ArrangementConfigUtil {
private static <T> void processData(@NotNull ArrangementStandardSettingsAware filter,
@Nullable ArrangementMatchCondition settings,
@NotNull Map<ArrangementSettingType, Collection<?>> result,
@NotNull Map<ArrangementSettingType, Set<?>> result,
@NotNull ArrangementSettingType type,
@NotNull T[] values)
{
List<T> data = null;
Set<T> data = null;
for (T v : values) {
if (!isEnabled(v, filter, settings)) {
continue;
}
if (data == null) {
data = new ArrayList<T>();
data = new HashSet<T>();
}
data.add(v);
}
@@ -122,6 +122,10 @@ public class ArrangementListRowDecorator extends JPanel implements ArrangementMa
if (!beingEdited && !myUnderMouse) {
myEditButton.setVisible(false);
}
if (beingEdited && !myBeingEdited) {
myEditButton.setVisible(true);
myEditButton.getPresentation().putClientProperty(Toggleable.SELECTED_PROPERTY, true);
}
myBeingEdited = beingEdited;
}
@@ -32,11 +32,16 @@ import java.awt.*;
*/
public class TitleWithToolbar extends JPanel {
public TitleWithToolbar(@NotNull String title, @NotNull String actionGroupId, @NotNull String place) {
public TitleWithToolbar(@NotNull String title,
@NotNull String actionGroupId,
@NotNull String place,
@NotNull JComponent targetComponent)
{
super(new GridBagLayout());
ActionManager actionManager = ActionManager.getInstance();
ActionGroup group = (ActionGroup)actionManager.getAction(actionGroupId);
ActionToolbar actionToolbar = actionManager.createActionToolbar(place, group, true);
actionToolbar.setTargetComponent(targetComponent);
add(new MyTitleComponent(title), new GridBag().weightx(1).anchor(GridBagConstraints.WEST).fillCellHorizontally());
add(actionToolbar.getComponent(), new GridBag().anchor(GridBagConstraints.CENTER));
@@ -15,9 +15,6 @@
*/
package com.intellij.execution.impl;
import static com.intellij.execution.impl.ConsoleViewImpl.TokenInfo;
import static com.intellij.execution.impl.ConsoleViewImpl.HyperlinkTokenInfo;
import com.intellij.execution.filters.HyperlinkInfo;
import com.intellij.execution.ui.ConsoleViewContentType;
import org.jetbrains.annotations.NotNull;
@@ -25,6 +22,9 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
import static com.intellij.execution.impl.ConsoleViewImpl.HyperlinkTokenInfo;
import static com.intellij.execution.impl.ConsoleViewImpl.TokenInfo;
/**
* Holds utility methods for console processing.
*
@@ -36,7 +36,7 @@ public class ConsoleUtil {
private ConsoleUtil() {
}
public static void addToken(int length, @Nullable HyperlinkInfo info, ConsoleViewContentType contentType, List<TokenInfo> tokens) {
public static void addToken(int length, @Nullable HyperlinkInfo info, ConsoleViewContentType contentType, @NotNull List<TokenInfo> tokens) {
int startOffset = 0;
if (!tokens.isEmpty()) {
final TokenInfo lastToken = tokens.get(tokens.size() - 1);
@@ -272,7 +272,10 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
});
}
protected ConsoleViewImpl(@NotNull final Project project, @NotNull GlobalSearchScope searchScope, boolean viewer, @Nullable FileType fileType,
protected ConsoleViewImpl(@NotNull final Project project,
@NotNull GlobalSearchScope searchScope,
boolean viewer,
@Nullable FileType fileType,
@NotNull final ConsoleState initialState) {
super(new BorderLayout());
isViewer = viewer;
@@ -480,7 +483,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
myEditor = null;
myHyperlinks = null;
}
}
}
private void cancelAllFlushRequests() {
synchronized (myCurrentRequests) {
@@ -1516,7 +1519,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
startOffset = info.endOffset;
}
else {
startOffset = Math.max(deferredOffset, info.startOffset);
startOffset = Math.max(deferredOffset, Math.max(info.startOffset, offset));
}
buffer.addUserText(startOffset - deferredOffset, textToUse);
@@ -336,6 +336,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
Container parent = processIcon.getParent();
parent.remove(processIcon);
parent.repaint();
pingEDT.ping(); // repaint title
synchronized (usages) {
if (visibleNodes.isEmpty()) {
if (usages.isEmpty()) {
@@ -422,7 +423,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
@Override
public void removeRangeFromModel(int start, int end) {
for (int i=end-1; i>=start; i--) {
for (int i=end; i>=start; i--) {
removeRow(i);
}
}
@@ -504,7 +505,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
if (shortcut != null) {
shortcutText = "(" + KeymapUtil.getShortcutText(shortcut) + ")";
}
return new InplaceButton("Options..." + shortcutText, AllIcons.General.Settings, new ActionListener() {
return new InplaceButton("Settings..." + shortcutText, AllIcons.General.Settings, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@@ -187,7 +187,7 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameItemProvider
private static boolean matchesQualifier(final Object element,
@NotNull final ChooseByNameBase base,
final List<Pair<String, MinusculeMatcher>> patternsAndMatchers) {
@NotNull List<Pair<String, MinusculeMatcher>> patternsAndMatchers) {
final String name = base.getModel().getFullName(element);
if (name == null) return false;
@@ -220,6 +220,7 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameItemProvider
return true;
}
@NotNull
private static List<Pair<String, MinusculeMatcher>> getPatternsAndMatchers(String qualifierPattern, final ChooseByNameBase base) {
return ContainerUtil.map2List(split(qualifierPattern, base), new Function<String, Pair<String, MinusculeMatcher>>() {
@NotNull
@@ -83,7 +83,6 @@ public class ModelDiff {
@Override
public void apply() {
//System.out.println("removing: "+this);
myListModel.removeRangeFromModel(start, end);
}
@@ -55,8 +55,14 @@ public abstract class Task implements TaskInfo, Progressive {
myCanBeCancelled = canBeCancelled;
}
/**
* This callback will be invoked on AWT dispatch thread.
*/
public void onCancel() {}
/**
* This callback will be invoked on AWT dispatch thread.
*/
public void onSuccess() {}
public final Project getProject() {
@@ -56,6 +56,10 @@ public class MacFileChooserDialogImpl implements PathChooserDialog {
private static final Callback SHOULD_ENABLE_URL = new Callback() {
@SuppressWarnings("UnusedDeclaration")
public boolean callback(ID self, String selector, ID panel, ID url) {
if (ourImplMap.get(self) == null) {
// Since it has already been removed from the map, the file is likely to be valid if the user was able to select it
return true;
}
if (url == null || url.intValue() == 0) return false;
final ID filename = Foundation.invoke(url, "path");
final String fileName = Foundation.toStringViaUTF8(filename);
@@ -561,8 +561,8 @@ arrangement.text.modifier=Modifier
arrangement.text.negate=Negate
arrangement.action.rule.add.text=Add rule
arrangement.action.rule.add.description=Add new arrangement rule
arrangement.action.rule.remove.text=Remove rule
arrangement.action.rule.remove.description=Remove selected arrangement rule
arrangement.action.rule.remove.text=Remove rule(s)
arrangement.action.rule.remove.description=Remove selected arrangement rule(s)
arrangement.action.rule.edit.text=Edit rule
arrangement.action.rule.edit.description=Edit selected arrangement rule
arrangement.action.rule.move.up.text=Move up
@@ -828,13 +828,13 @@
class="com.intellij.application.options.codeStyle.arrangement.action.MoveArrangementRuleDownAction"
icon="AllIcons.ToolbarDecorator.MoveDown"/>
<group id="Arrangement.RuleEditor.Context.Menu">
<group id="Arrangement.Rule.Match.Control.Context.Menu">
<reference ref="Arrangement.Rule.Add"/>
<reference ref="Arrangement.Rule.Remove"/>
<reference ref="Arrangement.Rule.Edit"/>
</group>
<group id="Arrangement.RuleEditor.ToolBar">
<group id="Arrangement.Rule.Match.Control.ToolBar">
<reference ref="Arrangement.Rule.Add"/>
<reference ref="Arrangement.Rule.Remove"/>
<reference ref="Arrangement.Rule.Move.Up"/>
@@ -21,6 +21,7 @@ import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ModuleRootModel;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
@@ -29,7 +30,9 @@ public interface DirectoryIndexExcludePolicy {
ExtensionPointName<DirectoryIndexExcludePolicy> EP_NAME = ExtensionPointName.create("com.intellij.directoryIndexExcludePolicy");
boolean isExcludeRoot(VirtualFile file);
boolean isExcludeRootForModule(final Module module, final VirtualFile file);
boolean isExcludeRootForModule(@NotNull Module module, final VirtualFile file);
@NotNull
VirtualFile[] getExcludeRootsForProject();
VirtualFilePointer[] getExcludeRootsForModule(ModuleRootModel rootModel);
@NotNull
VirtualFilePointer[] getExcludeRootsForModule(@NotNull ModuleRootModel rootModel);
}
@@ -35,7 +35,7 @@ import org.jetbrains.annotations.TestOnly;
import java.util.*;
public class DirectoryInfo {
public final class DirectoryInfo {
private Module module; // module to which content it belongs or null
private VirtualFile libraryClassRoot; // class root in library
private VirtualFile contentRoot;
@@ -53,6 +53,9 @@ public class DirectoryInfo {
*/
private OrderEntry[] orderEntries;
public DirectoryInfo() {
}
@TestOnly
@SuppressWarnings({"unchecked"})
public boolean equals(Object o) {
@@ -237,7 +240,7 @@ public class DirectoryInfo {
}
};
static final Comparator<OrderEntry> BY_OWNER_MODULE = new Comparator<OrderEntry>() {
public static final Comparator<OrderEntry> BY_OWNER_MODULE = new Comparator<OrderEntry>() {
@Override
public int compare(OrderEntry o1, OrderEntry o2) {
String name1 = o1.getOwnerModule().getName();
@@ -246,7 +249,7 @@ public class DirectoryInfo {
}
};
void setInternedOrderEntries(@NotNull OrderEntry[] internedOrderEntries) {
public void setInternedOrderEntries(@NotNull OrderEntry[] internedOrderEntries) {
orderEntries = internedOrderEntries;
}
@@ -139,7 +139,7 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra
private final GroupNode myRoot;
private final UsageViewTreeModelBuilder myModel;
private final Object lock = new Object();
private Splitter myTreeSplitter;
private Splitter myPreviewSplitter;
public UsageViewImpl(@NotNull final Project project,
@NotNull UsageViewPresentation presentation,
@@ -266,13 +266,13 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra
disposeUsageContextPanels();
JScrollPane treePane = ScrollPaneFactory.createScrollPane(myTree);
myTreeSplitter = new Splitter();
myTreeSplitter.setFirstComponent(treePane);
myPreviewSplitter = new Splitter(false, 0.5f, 0.1f, 0.9f);
myPreviewSplitter.setFirstComponent(treePane);
myCentralPanel.add(myTreeSplitter, BorderLayout.CENTER);
myCentralPanel.add(myPreviewSplitter, BorderLayout.CENTER);
if (UsageViewSettings.getInstance().IS_PREVIEW_USAGES) {
myTreeSplitter.setProportion(UsageViewSettings.getInstance().PREVIEW_USAGES_SPLITTER_PROPORTIONS);
myPreviewSplitter.setProportion(UsageViewSettings.getInstance().PREVIEW_USAGES_SPLITTER_PROPORTIONS);
treePane.putClientProperty(UIUtil.KEEP_BORDER_SIDES, SideBorder.RIGHT);
final JBTabbedPane tabbedPane = new JBTabbedPane(SwingConstants.BOTTOM){
@NotNull
@@ -316,10 +316,10 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra
});
tabbedPane.setBorder(IdeBorderFactory.createBorder(SideBorder.LEFT));
myTreeSplitter.setSecondComponent(tabbedPane);
myPreviewSplitter.setSecondComponent(tabbedPane);
}
else {
myTreeSplitter.setProportion(1);
myPreviewSplitter.setProportion(1);
}
myCentralPanel.add(myButtonPanel, BorderLayout.SOUTH);
@@ -330,13 +330,13 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra
private void tabSelected(@NotNull final UsageContextPanel.Provider provider) {
myCurrentUsageContextProvider = provider;
saveSplitterProportions();
setupCentralPanel();
updateOnSelectionChanged();
}
private void disposeUsageContextPanels() {
if (myCurrentUsageContextPanel != null) {
saveSplitterProportions();
Disposer.dispose(myCurrentUsageContextPanel);
myCurrentUsageContextPanel = null;
}
@@ -607,7 +607,6 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra
});
excludeUsages(excludedUsages.toArray(new Usage[excludedUsages.size()]));
if (myCentralPanel != null) {
saveSplitterProportions();
setupCentralPanel();
}
SwingUtilities.invokeLater(new Runnable() {
@@ -937,15 +936,11 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra
@Override
public void close() {
saveSplitterProportions();
UsageViewManager.getInstance(myProject).closeContent(myContent);
}
private void saveSplitterProportions() {
if (UsageViewSettings.getInstance().IS_PREVIEW_USAGES) {
UsageViewSettings.getInstance().PREVIEW_USAGES_SPLITTER_PROPORTIONS = myTreeSplitter.getProportion();
}
UsageViewSettings.getInstance().PREVIEW_USAGES_SPLITTER_PROPORTIONS = myPreviewSplitter.getProportion();
}
@Override
@@ -217,16 +217,8 @@ public class StringUtil extends StringUtilRt {
fromIndex = 0;
}
int max = sourceCount - 1;
for (int i = fromIndex; i <= max; i++) {
/* Look for first character. */
if (!charsEqualIgnoreCase(where.charAt(i), what)) {
while (++i <= max && !charsEqualIgnoreCase(where.charAt(i), what)) ;
}
/* Found first character, now look at the rest of v2 */
if (i <= max) {
for (int i = fromIndex; i < sourceCount; i++) {
if (charsEqualIgnoreCase(where.charAt(i), what)) {
return i;
}
}
@@ -19,16 +19,16 @@ package com.intellij.util;
* @since 27.03.2012
*/
public class BitUtil {
public static boolean isSet(final byte value, final byte flag) {
return (value & flag) == flag;
public static boolean isSet(final byte value, final byte mask) {
return (value & mask) == mask;
}
public static boolean isSet(final int value, final int flag) {
return (value & flag) == flag;
public static boolean isSet(final int value, final int mask) {
return (value & mask) == mask;
}
public static boolean notSet(final int value, final int mask) {
return (value & mask) == 0;
return (value & mask) != mask;
}
/**
@@ -128,10 +128,12 @@ public class IOUtil {
public static boolean isAscii(final String str) {
for (int i = 0; i != str.length(); ++ i) {
final char c = str.charAt(i);
if (c < 0 || c >= 128) {
return false;
}
if (!isAscii(c)) return false;
}
return true;
}
public static boolean isAscii(char c) {
return c >= 0 && c < 128;
}
}
@@ -268,8 +268,8 @@ printstacktrace.call.display.name=Call to 'printStackTrace()'
printstacktrace.call.problem.descriptor=Call to <code>#ref()</code> should probably be replaced with more robust logging #loc
todo.comment.display.name=TODO comment
todo.comment.problem.descriptor=TODO comment <code>#ref</code> #loc
abstract.method.call.in.constructor.display.name=Abstract method call in constructor
abstract.method.call.in.constructor.problem.descriptor=Call to abstract method <code>#ref()</code> during object construction #loc
abstract.method.call.in.constructor.display.name=Abstract method called during object construction
abstract.method.call.in.constructor.problem.descriptor=Call to 'abstract' method <code>#ref()</code> during object construction #loc
instance.variable.may.not.be.initialized.display.name=Instance field may not be initialized
instance.variable.may.not.be.initialized.problem.descriptor=Instance field <code>#ref</code> may not be initialized during object construction #loc
instance.Variable.may.not.be.initialized.problem.descriptor.junit=Instance field <code>#ref</code> may not be initialized during object construction or 'setUp()' call #loc
@@ -278,9 +278,9 @@ instance.variable.used.before.initialized.display.name=Instance field used befor
instance.variable.used.before.initialized.problem.descriptor=Instance field <code>#ref</code> used before initialized #loc
non.final.static.variable.initialization.display.name=Non-final static field is used during class initialization
non.final.static.variable.initialization.problem.descriptor=Non-final static field <code>#ref</code> used during class initialization #loc
overridable.method.call.in.constructor.display.name=Overridable method call during object construction
overridable.method.call.in.constructor.problem.descriptor=Call to overridable method during object construction #loc
overridden.method.call.in.constructor.display.name=Overridden method call during object construction
overridable.method.call.in.constructor.display.name=Overridable method called during object construction
overridable.method.call.in.constructor.problem.descriptor=Call to overridable method <code>#ref()</code> during object construction #loc
overridden.method.call.in.constructor.display.name=Overridden method called during object construction
overridden.method.call.in.constructor.problem.descriptor=Call to overridden method <code>#ref()</code> during object construction #loc
static.variable.may.not.be.initialized.display.name=Static field may not be initialized
static.variable.may.not.be.initialized.problem.descriptor=Static field <code>#ref</code> may not be initialized during class initialization #loc
@@ -358,6 +358,7 @@ string.concatenation.ignore.exceptions.option=Ignore for throwable arguments
string.concatenation.ignore.constant.initializers.option=Ignore for initializers of constants
ignore.in.test.code=Ignore in &test code
ignore.in.annotations=Ignore in annotations
ignore.in.tostring=Ignore inside toString() methods
string.equalsignorecase.call.display.name=Call to 'String.equalsIgnoreCase()'
string.equalsignorecase.call.problem.descriptor=<code>String.#ref()</code> using internationalized strings #loc
string.equals.call.display.name=Call to 'String.equals()'
@@ -1623,7 +1624,7 @@ unpredictable.big.decimal.constructor.call.quickfix=Replace with ''new BigDecima
unnecessary.unary.minus.display.name=Unnecessary unary minus
unnecessary.unary.minus.problem.descriptor=Unnecessary unary minus #loc
unnecessary.unary.minus.quickfix=Remove unary minus and invert parent operation sign
make.field.final.quickfix=Make ''{0}'' final
make.field.final.quickfix=Make ''{0}'' ''final''
increment.decrement.used.as.expression.quickfix=Extract ''{0}'' to separate statement
ignore.classes.in.hierarchy.column.name=Ignore subclasses of
overly.strong.type.cast.ignore.in.matching.instanceof.option=Ignore casts with a matching instanceof expression
@@ -28,6 +28,7 @@ import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.DelegatingFix;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.MethodUtils;
import com.siyeh.ig.psiutils.TestUtils;
import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.NonNls;
@@ -58,72 +59,58 @@ public class StringConcatenationInspection extends BaseInspection {
@SuppressWarnings({"PublicField"})
public boolean ignoreInTestCode = false;
@SuppressWarnings("PublicField")
public boolean ignoreInToString = false;
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"string.concatenation.display.name");
return InspectionGadgetsBundle.message("string.concatenation.display.name");
}
@Override
@NotNull
public String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message(
"string.concatenation.problem.descriptor");
return InspectionGadgetsBundle.message("string.concatenation.problem.descriptor");
}
@Override
@NotNull
protected InspectionGadgetsFix[] buildFixes(Object... infos) {
final PsiPolyadicExpression polyadicExpression =
(PsiPolyadicExpression)infos[0];
final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)infos[0];
final Collection<InspectionGadgetsFix> result = new ArrayList();
final PsiElement parent = polyadicExpression.getParent();
if (parent instanceof PsiVariable) {
final PsiVariable variable = (PsiVariable)parent;
final InspectionGadgetsFix fix = new DelegatingFix(
new AddAnnotationFix(AnnotationUtil.NON_NLS, variable));
final InspectionGadgetsFix fix = new DelegatingFix(new AddAnnotationFix(AnnotationUtil.NON_NLS, variable));
result.add(fix);
}
else if (parent instanceof PsiAssignmentExpression) {
final PsiAssignmentExpression assignmentExpression =
(PsiAssignmentExpression)parent;
final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)parent;
final PsiExpression lhs = assignmentExpression.getLExpression();
if (lhs instanceof PsiReferenceExpression) {
final PsiReferenceExpression referenceExpression =
(PsiReferenceExpression)lhs;
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)lhs;
final PsiElement target = referenceExpression.resolve();
if (target instanceof PsiModifierListOwner) {
final PsiModifierListOwner modifierListOwner =
(PsiModifierListOwner)target;
final InspectionGadgetsFix fix = new DelegatingFix(
new AddAnnotationFix(AnnotationUtil.NON_NLS,
modifierListOwner));
final PsiModifierListOwner modifierListOwner = (PsiModifierListOwner)target;
final InspectionGadgetsFix fix = new DelegatingFix(new AddAnnotationFix(AnnotationUtil.NON_NLS, modifierListOwner));
result.add(fix);
}
}
}
final PsiExpression[] operands = polyadicExpression.getOperands();
for (PsiExpression operand : operands) {
final PsiModifierListOwner element1 =
getAnnotatableElement(operand);
final PsiModifierListOwner element1 = getAnnotatableElement(operand);
if (element1 != null) {
final InspectionGadgetsFix fix = new DelegatingFix(
new AddAnnotationFix(AnnotationUtil.NON_NLS, element1));
final InspectionGadgetsFix fix = new DelegatingFix(new AddAnnotationFix(AnnotationUtil.NON_NLS, element1));
result.add(fix);
}
}
final PsiElement expressionParent = PsiTreeUtil.getParentOfType(
polyadicExpression, PsiReturnStatement.class,
PsiExpressionList.class);
if (!(expressionParent instanceof PsiExpressionList) &&
expressionParent != null) {
final PsiMethod method =
PsiTreeUtil.getParentOfType(expressionParent,
PsiMethod.class);
final PsiElement expressionParent = PsiTreeUtil.getParentOfType(polyadicExpression, PsiReturnStatement.class, PsiExpressionList.class);
if (!(expressionParent instanceof PsiExpressionList) && expressionParent != null) {
final PsiMethod method = PsiTreeUtil.getParentOfType(expressionParent, PsiMethod.class);
if (method != null) {
final InspectionGadgetsFix fix = new DelegatingFix(
new AddAnnotationFix(AnnotationUtil.NON_NLS, method));
final InspectionGadgetsFix fix = new DelegatingFix(new AddAnnotationFix(AnnotationUtil.NON_NLS, method));
result.add(fix);
}
}
@@ -131,13 +118,11 @@ public class StringConcatenationInspection extends BaseInspection {
}
@Nullable
public static PsiModifierListOwner getAnnotatableElement(
PsiExpression expression) {
public static PsiModifierListOwner getAnnotatableElement(PsiExpression expression) {
if (!(expression instanceof PsiReferenceExpression)) {
return null;
}
final PsiReferenceExpression referenceExpression =
(PsiReferenceExpression)expression;
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression;
final PsiElement element = referenceExpression.resolve();
if (!(element instanceof PsiModifierListOwner)) {
return null;
@@ -156,6 +141,7 @@ public class StringConcatenationInspection extends BaseInspection {
optionsPanel.addCheckbox(InspectionGadgetsBundle.message("string.concatenation.ignore.constant.initializers.option"),
"ignoreConstantInitializers");
optionsPanel.addCheckbox(InspectionGadgetsBundle.message("ignore.in.test.code"), "ignoreInTestCode");
optionsPanel.addCheckbox(InspectionGadgetsBundle.message("ignore.in.tostring"), "ignoreInToString");
return optionsPanel;
}
@@ -164,12 +150,10 @@ public class StringConcatenationInspection extends BaseInspection {
return new StringConcatenationVisitor();
}
private class StringConcatenationVisitor
extends BaseInspectionVisitor {
private class StringConcatenationVisitor extends BaseInspectionVisitor {
@Override
public void visitPolyadicExpression(
@NotNull PsiPolyadicExpression expression) {
public void visitPolyadicExpression(@NotNull PsiPolyadicExpression expression) {
super.visitPolyadicExpression(expression);
final IElementType tokenType = expression.getOperationTokenType();
if (!JavaTokenType.PLUS.equals(tokenType)) {
@@ -185,7 +169,7 @@ public class StringConcatenationInspection extends BaseInspection {
return;
}
}
if (isInsideAnnotation(expression)) {
if (AnnotationUtil.isInsideAnnotation(expression)) {
return;
}
if (ignoreInTestCode && TestUtils.isInTestCode(expression)) {
@@ -193,46 +177,32 @@ public class StringConcatenationInspection extends BaseInspection {
}
if (ignoreAsserts) {
final PsiAssertStatement assertStatement =
PsiTreeUtil.getParentOfType(expression,
PsiAssertStatement.class, true,
PsiCodeBlock.class);
PsiTreeUtil.getParentOfType(expression, PsiAssertStatement.class, true, PsiCodeBlock.class);
if (assertStatement != null) {
return;
}
}
if (ignoreSystemErrs || ignoreSystemOuts) {
final PsiMethodCallExpression methodCallExpression =
PsiTreeUtil.getParentOfType(expression,
PsiMethodCallExpression.class, true,
PsiCodeBlock.class);
PsiTreeUtil.getParentOfType(expression, PsiMethodCallExpression.class, true, PsiCodeBlock.class);
if (methodCallExpression != null) {
final PsiReferenceExpression methodExpression =
methodCallExpression.getMethodExpression();
final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
@NonNls
final String canonicalText =
methodExpression.getCanonicalText();
if (ignoreSystemOuts &&
"System.out.println".equals(canonicalText) ||
"System.out.print".equals(canonicalText)) {
final String canonicalText = methodExpression.getCanonicalText();
if (ignoreSystemOuts && "System.out.println".equals(canonicalText) || "System.out.print".equals(canonicalText)) {
return;
}
if (ignoreSystemErrs &&
"System.err.println".equals(canonicalText) ||
"System.err.print".equals(canonicalText)) {
if (ignoreSystemErrs && "System.err.println".equals(canonicalText) || "System.err.print".equals(canonicalText)) {
return;
}
}
}
if (ignoreThrowableArguments) {
final PsiNewExpression newExpression =
PsiTreeUtil.getParentOfType(expression,
PsiNewExpression.class, true,
PsiCodeBlock.class);
PsiTreeUtil.getParentOfType(expression, PsiNewExpression.class, true, PsiCodeBlock.class);
if (newExpression != null) {
final PsiType newExpressionType = newExpression.getType();
if (newExpressionType != null &&
InheritanceUtil.isInheritor(newExpressionType,
"java.lang.Throwable")) {
if (newExpressionType != null && InheritanceUtil.isInheritor(newExpressionType, "java.lang.Throwable")) {
return;
}
}
@@ -244,17 +214,21 @@ public class StringConcatenationInspection extends BaseInspection {
}
if (parent instanceof PsiField) {
final PsiField field = (PsiField)parent;
if (field.hasModifierProperty(PsiModifier.STATIC) &&
field.hasModifierProperty(PsiModifier.FINAL)) {
if (field.hasModifierProperty(PsiModifier.STATIC) && field.hasModifierProperty(PsiModifier.FINAL)) {
return;
}
final PsiClass containingClass = field.getContainingClass();
if (containingClass != null &&
containingClass.isInterface()) {
if (containingClass != null && containingClass.isInterface()) {
return;
}
}
}
if (ignoreInToString) {
final PsiMethod method = PsiTreeUtil.getParentOfType(expression, PsiMethod.class, true, PsiClass.class);
if (MethodUtils.isToString(method)) {
return;
}
}
if (NonNlsUtils.isNonNlsAnnotatedUse(expression)) {
return;
}
@@ -263,24 +237,12 @@ public class StringConcatenationInspection extends BaseInspection {
if (!ExpressionUtils.isStringConcatenationOperand(operand)) {
continue;
}
final PsiJavaToken token =
expression.getTokenBeforeOperand(operand);
final PsiJavaToken token = expression.getTokenBeforeOperand(operand);
if (token == null) {
continue;
}
registerError(token, expression);
}
}
private boolean isInsideAnnotation(PsiExpression expression) {
while (true) {
final PsiElement parent = expression.getParent();
if (!(parent instanceof PsiPolyadicExpression)) {
return parent instanceof PsiArrayInitializerMemberValue ||
parent instanceof PsiNameValuePair;
}
expression = (PsiExpression)parent;
}
}
}
}
@@ -22,6 +22,8 @@ of constant fields.
<p>
Use the sixth checkbox to ignore string concatenations in test code.
<p>
Use the seventh checkbox to ignore string concatentations inside <b>toString()</b> methods.
<p>
<small>Powered by InspectionGadgets</small>
</body>
</html>
@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.groovy.griffon.GriffonCreateProjectDialog">
<grid id="27dc6" binding="myComponent" layout-manager="GridLayoutManager" row-count="6" column-count="3" 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="162"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="8db57" class="javax.swing.JLabel">
<constraints>
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="e4473"/>
<text value="Additional &amp;options:"/>
</properties>
</component>
<component id="e4473" class="javax.swing.JTextField" binding="myOptionField">
<constraints>
<grid row="5" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<minimum-size width="150" height="-1"/>
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties>
<columns value="100"/>
</properties>
</component>
<component id="64b00" class="javax.swing.JRadioButton" binding="myCreateApp" default-binding="true">
<constraints>
<grid row="1" 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>
<selected value="true"/>
<text value="Create an &amp;application (create-app)"/>
</properties>
</component>
<component id="34959" class="javax.swing.JRadioButton" binding="myCreatePlugin">
<constraints>
<grid row="2" 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="Create a &amp;plugin (create-plugin)"/>
</properties>
</component>
<component id="58a43" class="javax.swing.JRadioButton" binding="myCreateAddon">
<constraints>
<grid row="3" 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="Create an a&amp;ddon (create-addon)"/>
</properties>
</component>
<component id="d9e96" class="javax.swing.JRadioButton" binding="myCreateArchetype">
<constraints>
<grid row="4" 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="Create an a&amp;rchetype (create-archetype)"/>
</properties>
</component>
<component id="5fcd3" class="javax.swing.JLabel" binding="myCreateLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Label"/>
</properties>
</component>
</children>
</grid>
<buttonGroups>
<group name="myButtonGroup1">
<member id="64b00"/>
<member id="34959"/>
<member id="58a43"/>
<member id="d9e96"/>
</group>
</buttonGroups>
</form>
@@ -0,0 +1,69 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.griffon;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
/**
* @author peter
*/
public class GriffonCreateProjectDialog extends DialogWrapper {
private JTextField myOptionField;
private JPanel myComponent;
private JRadioButton myCreateApp;
private JRadioButton myCreatePlugin;
private JRadioButton myCreateAddon;
private JRadioButton myCreateArchetype;
private JLabel myCreateLabel;
public GriffonCreateProjectDialog(@NotNull Module module) {
super(module.getProject());
setTitle("Create Griffon Structure");
myCreateLabel.setText("Create Griffon structure in module '" + module.getName() + "':");
init();
}
@Nullable
@Override
protected JComponent createCenterPanel() {
return myComponent;
}
String getCommand() {
if (myCreateAddon.isSelected()) return "create-addon";
if (myCreateApp.isSelected()) return "create-app";
if (myCreateArchetype.isSelected()) return "create-archetype";
if (myCreatePlugin.isSelected()) return "create-plugin";
throw new AssertionError("No selection");
}
String[] getArguments() {
String text = myOptionField.getText();
if (StringUtil.isEmptyOrSpaces(text)) {
return ArrayUtil.EMPTY_STRING_ARRAY;
}
return text.split(" ");
}
}
@@ -17,6 +17,7 @@
package org.jetbrains.plugins.groovy.griffon;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.JavaParameters;
import com.intellij.lang.properties.IProperty;
import com.intellij.lang.properties.psi.PropertiesFile;
@@ -36,9 +37,11 @@ import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.IgnoredBeanFactory;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.util.ArrayUtil;
import gnu.trove.TIntArrayList;
import icons.JetgroovyIcons;
import org.jetbrains.annotations.NonNls;
@@ -93,6 +96,18 @@ public class GriffonFramework extends MvcFramework {
public void upgradeFramework(@NotNull Module module) {
}
@Nullable
@Override
protected GeneralCommandLine getCreationCommandLine(Module module) {
GriffonCreateProjectDialog dialog = new GriffonCreateProjectDialog(module);
dialog.show();
if (!dialog.isOK()) {
return null;
}
return createCommandAndShowErrors(null, module, true, dialog.getCommand(), dialog.getArguments());
}
@Override
public boolean updatesWholeProject() {
return false;
@@ -269,7 +284,7 @@ public class GriffonFramework extends MvcFramework {
throw new ExecutionException("Failed to initialize griffon module: module " + module.getName() + " contains more than one root");
}
args = new String[]{roots[0].getName()};
args = ArrayUtil.mergeArrays(new String[]{roots[0].getName()}, args);
rootFile = roots[0].getParent();
}
else {
@@ -279,7 +294,7 @@ public class GriffonFramework extends MvcFramework {
}
}
String workDir = VfsUtil.virtualToIoFile(rootFile).getAbsolutePath();
String workDir = VfsUtilCore.virtualToIoFile(rootFile).getAbsolutePath();
if (jvmParams != null) {
params.getVMParametersList().addParametersString(jvmParams);
@@ -42,7 +42,7 @@ public class RemoveUnnecessaryEscapeCharactersIntention extends Intention {
final Document document = editor.getDocument();
final TextRange range = element.getTextRange();
document.replaceString(range.getStartOffset(), range.getEndOffset(), removeUnnecessaryEscapeSymbols(((GrLiteral)element)));
document.replaceString(range.getStartOffset(), range.getEndOffset(), removeUnnecessaryEscapeSymbols((GrLiteral)element));
}
@NotNull
@@ -51,9 +51,10 @@ public class RemoveUnnecessaryEscapeCharactersIntention extends Intention {
return new PsiElementPredicate() {
@Override
public boolean satisfiedBy(PsiElement element) {
final String text = element.getText();
String text;
return element instanceof GrLiteral &&
getStartQuote(text) != null &&
getStartQuote(text = element.getText()) != null &&
!removeUnnecessaryEscapeSymbols((GrLiteral)element).equals(text);
}
};
@@ -137,14 +137,7 @@ public abstract class MvcFramework {
ProjectSettingsService.getInstance(module.getProject()).showModuleConfigurationDialog(module.getName(), ClasspathEditor.NAME);
}
module.putUserData(CREATE_APP_STRUCTURE, null);
final int result = Messages.showYesNoCancelDialog(module.getProject(),
"Create default " + getDisplayName() + " directory structure in module '" + module.getName() + "'?",
"Create " + getDisplayName() + " application", "Run 'create-&app'", "Run 'create-&plugin'", "&Cancel", getIcon());
if (result < 0 || result > 1) {
return;
}
final GeneralCommandLine commandLine = createCommandAndShowErrors(null, module, true, result == 0 ? "create-app" : "create-plugin");
final GeneralCommandLine commandLine = getCreationCommandLine(module);
if (commandLine == null) return;
MvcConsole.executeProcess(module, commandLine, new Runnable() {
@@ -163,6 +156,18 @@ public abstract class MvcFramework {
}
@Nullable
protected GeneralCommandLine getCreationCommandLine(Module module) {
String message = "Create default " + getDisplayName() + " directory structure in module '" + module.getName() + "'?";
final int result = Messages.showDialog(module.getProject(), message, "Create " + getDisplayName() + " application",
new String[]{"Run 'create-&app'", "Run 'create-&plugin'", "&Cancel"}, 0, getIcon());
if (result < 0 || result > 1) {
return null;
}
return createCommandAndShowErrors(null, module, true, result == 0 ? "create-app" : "create-plugin");
}
public abstract void updateProjectStructure(@NotNull final Module module);
public abstract void ensureRunConfigurationExists(@NotNull Module module);
@@ -216,7 +216,7 @@ public class MavenFoldersImporter {
private void configGeneratedSourceFolder(@NotNull File targetDir, boolean isTestSources) {
switch (myImportingSettings.getGeneratedSourcesFolder()) {
case GENERATED_SOURCE_FOLDER:
myModel.addSourceFolder(targetDir.getPath(), isTestSources);
myModel.addSourceFolder(targetDir.getPath(), isTestSources, true);
break;
case SUBFOLDER:
@@ -242,7 +242,7 @@ public class MavenFoldersImporter {
private void addAsSourceFolder(@NotNull File dir, boolean isTestSources) {
if (!myModel.hasRegisteredSourceSubfolder(dir)) {
myModel.addSourceFolder(dir.getPath(), isTestSources);
myModel.addSourceFolder(dir.getPath(), isTestSources, true);
}
}
@@ -21,12 +21,12 @@ import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.idea.maven.MavenCustomRepositoryHelper;
import org.jetbrains.idea.maven.MavenImportingTestCase;
import org.jetbrains.idea.maven.project.MavenGeneralSettings;
import org.jetbrains.idea.maven.project.MavenImportingSettings;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import org.jetbrains.idea.maven.utils.Path;
import java.io.File;
import java.io.IOException;
public class FoldersImportingTest extends MavenImportingTestCase {
public void testSimpleProjectStructure() throws Exception {
@@ -646,8 +646,8 @@ public class FoldersImportingTest extends MavenImportingTestCase {
public void testAddingExistingGeneratedSourcesWithCustomTargetDir() throws Exception {
createStdProjectFolders();
createProjectSubDirs("targetCustom/generated-sources/src",
"targetCustom/generated-test-sources/test");
createProjectSubDirsWithFile("targetCustom/generated-sources/src",
"targetCustom/generated-test-sources/test");
importProject("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
@@ -859,10 +859,10 @@ public class FoldersImportingTest extends MavenImportingTestCase {
public void testDoesNotExcludeGeneratedSourcesUnderTargetDir() throws Exception {
createStdProjectFolders();
createProjectSubDirs("target/foo",
"target/bar",
"target/generated-sources/baz",
"target/generated-test-sources/bazz");
createProjectSubDirsWithFile("target/foo",
"target/bar",
"target/generated-sources/baz",
"target/generated-test-sources/bazz");
importProject("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
@@ -993,10 +993,10 @@ public class FoldersImportingTest extends MavenImportingTestCase {
public void testAnnotationProcessorSources() throws Exception {
createStdProjectFolders();
createProjectSubDirs("target/generated-sources/foo",
"target/generated-sources/annotations",
"target/generated-test-sources/test-annotations",
"target/generated-test-sources/foo");
createProjectSubDirsWithFile("target/generated-sources/foo",
"target/generated-sources/annotations",
"target/generated-test-sources/test-annotations",
"target/generated-test-sources/foo");
importProject("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
@@ -1017,14 +1017,13 @@ public class FoldersImportingTest extends MavenImportingTestCase {
public void testCustomAnnotationProcessorSources() throws Exception {
createStdProjectFolders();
createProjectSubDirs("anno",
"test-anno",
"target/generated-sources/foo",
"target/generated-sources/annotations",
"target/generated-sources/test-annotations",
"target/generated-test-sources/foo");
createProjectSubDirsWithFile("anno",
"target/generated-sources/foo",
"target/generated-sources/annotations",
"target/generated-sources/test-annotations",
"target/generated-test-sources/foo");
createProjectSubFile("anno/aaa.java");
createProjectSubDir("test-anno");
importProject("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
@@ -1061,4 +1060,10 @@ public class FoldersImportingTest extends MavenImportingTestCase {
private CompilerModuleExtension getCompilerExtension(String moduleName) {
return ModuleRootManager.getInstance(getModule(moduleName)).getModuleExtension(CompilerModuleExtension.class);
}
private void createProjectSubDirsWithFile(String ... dirs) throws IOException {
for (String dir : dirs) {
createProjectSubFile(dir + "/a.txt");
}
}
}