Merge branch 'master' of git.labs.intellij.net:idea/community

This commit is contained in:
Kirill.Safonov
2010-06-30 18:50:12 +04:00
8 changed files with 292 additions and 36 deletions
@@ -8,5 +8,6 @@
<lang.syntaxHighlighterFactory key="RegExp" implementationClass="org.intellij.lang.regexp.RegExpSyntaxHighlighterFactory"/>
<lang.braceMatcher language="RegExp" implementationClass="org.intellij.lang.regexp.RegExpBraceMatcher"/>
<lang.surroundDescriptor language="RegExp" implementationClass="org.intellij.lang.regexp.surroundWith.SimpleSurroundDescriptor"/>
<colorSettingsPage implementation="org.intellij.lang.regexp.RegExpColorsPage"/>
</extensions>
</idea-plugin>
@@ -0,0 +1,81 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.intellij.lang.regexp;
import com.intellij.application.options.colors.InspectionColorSettingsPage;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.fileTypes.SyntaxHighlighter;
import com.intellij.openapi.options.colors.AttributesDescriptor;
import com.intellij.openapi.options.colors.ColorDescriptor;
import com.intellij.openapi.options.colors.ColorSettingsPage;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.Map;
/**
* @author traff
*/
public class RegExpColorsPage implements ColorSettingsPage, InspectionColorSettingsPage {
private static final AttributesDescriptor[] ATTRS = new AttributesDescriptor[] {
new AttributesDescriptor("Keywords", RegExpHighlighter.META),
new AttributesDescriptor("Escaped characters", RegExpHighlighter.ESC_CHARACTER),
new AttributesDescriptor("Braces", RegExpHighlighter.BRACES),
new AttributesDescriptor("Brackets", RegExpHighlighter.BRACKETS),
new AttributesDescriptor("Parenthesis", RegExpHighlighter.PARENTHS),
};
@NonNls private static final HashMap<String,TextAttributesKey> ourTagToDescriptorMap = new HashMap<String, TextAttributesKey>();
@NotNull
public String getDisplayName() {
return "RegExp";
}
public Icon getIcon() {
return RegExpFileType.INSTANCE.getIcon();
}
@NotNull
public AttributesDescriptor[] getAttributeDescriptors() {
return ATTRS;
}
@NotNull
public ColorDescriptor[] getColorDescriptors() {
return ColorDescriptor.EMPTY_ARRAY;
}
@NotNull
public SyntaxHighlighter getHighlighter() {
final SyntaxHighlighter highlighter = SyntaxHighlighter.PROVIDER.create(RegExpFileType.INSTANCE, null, null);
assert highlighter != null;
return highlighter;
}
@NotNull
public String getDemoText() {
return
"^[\\w\\.-]+@([\\w\\-]+\\.)+[A-Z]{2,4}$";
}
public Map<String, TextAttributesKey> getAdditionalHighlightingTagToDescriptorMap() {
return ourTagToDescriptorMap;
}
}
@@ -14,12 +14,6 @@
* limitations under the License.
*/
/*
* Created by IntelliJ IDEA.
* User: Anna.Kozlova
* Date: 05-Nov-2006
* Time: 18:04:58
*/
package com.intellij.codeInsight.intention;
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
@@ -28,9 +22,45 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Anna Kozlova
* @author Konstantin Bulenkov
*/
public abstract class PsiElementBaseIntentionAction extends BaseIntentionAction {
/**
* Invokes intention action for the element under cursor
*
* @param project the project in which the file is opened.
* @param editor the editor for the file
* @param element the element under cursor
* @throws com.intellij.util.IncorrectOperationException ...
*/
public void invoke(Project project, Editor editor, PsiElement element) throws IncorrectOperationException {
throw new IncorrectOperationException();
}
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
final PsiElement element = getElement(editor, file);
return element == null ? false : isAvailable(project, editor, element);
}
@Nullable
protected static PsiElement getElement(Editor editor, PsiFile file) {
if (!file.getManager().isInProject(file)) return null;
final CaretModel caretModel = editor.getCaretModel();
final int position = caretModel.getOffset();
return file.findElementAt(position);
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
invoke(project, editor, getElement(editor, file));
}
/**
* Checks whether this intention is available at a caret offset in file.
@@ -42,13 +72,4 @@ public abstract class PsiElementBaseIntentionAction extends BaseIntentionAction
* @return true if the intention is available, false otherwise.
*/
public abstract boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element);
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
if (!file.getManager().isInProject(file)) return false;
final CaretModel caretModel = editor.getCaretModel();
final int position = caretModel.getOffset();
final PsiElement element = file.findElementAt(position);
if (element == null) return false;
return isAvailable(project, editor, element);
}
}
@@ -2,4 +2,4 @@
<body>
<font face="verdana" size="-1">This inspection detects missing html-description for an inspection.</font>
</body>
</html>
</html>
@@ -17,18 +17,22 @@ package org.jetbrains.idea.devkit;
import com.intellij.codeInspection.InspectionToolProvider;
import org.jetbrains.idea.devkit.inspections.ComponentNotRegisteredInspection;
import org.jetbrains.idea.devkit.inspections.DescriptionNotFoundInspection;
import org.jetbrains.idea.devkit.inspections.InspectionDescriptionNotFoundInspection;
import org.jetbrains.idea.devkit.inspections.IntentionDescriptionNotFoundInspection;
import org.jetbrains.idea.devkit.inspections.PluginXmlDomInspection;
/**
* @author Konstantin Bulenkov
*/
public class DevKitInspectionToolProvider implements InspectionToolProvider {
public Class[] getInspectionClasses() {
return new Class[] {
//RegistrationProblemsInspection.class,
PluginXmlDomInspection.class,
ComponentNotRegisteredInspection.class,
DescriptionNotFoundInspection.class
InspectionDescriptionNotFoundInspection.class,
IntentionDescriptionNotFoundInspection.class
};
}
}
}
@@ -41,7 +41,7 @@ import java.util.List;
/**
* @author Konstantin Bulenkov
*/
public class DescriptionNotFoundInspection extends DevKitInspectionBase{
public class InspectionDescriptionNotFoundInspection extends DevKitInspectionBase{
@NonNls private static final String INSPECTION_PROFILE_ENTRY = "com.intellij.codeInspection.InspectionProfileEntry";
@NonNls private static final String INSPECTION_DESCRIPTIONS = "inspectionDescriptions";
@@ -77,7 +77,7 @@ public class DescriptionNotFoundInspection extends DevKitInspectionBase{
final PsiElement problem = getProblemElement(aClass, method);
final ProblemDescriptor problemDescriptor = manager
.createProblemDescriptor(problem == null ? nameIdentifier : problem,
"Inspection does not have a description", isOnTheFly, new LocalQuickFix[]{new CreateHtmlDescriptionFix(filename, module)},
"Inspection does not have a description", isOnTheFly, new LocalQuickFix[]{new CreateHtmlDescriptionFix(filename, module, false)},
ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
return new ProblemDescriptor[]{problemDescriptor};
}
@@ -152,7 +152,7 @@ public class DescriptionNotFoundInspection extends DevKitInspectionBase{
@NotNull
public String getShortName() {
return "DescriptionNotFoundInspection";
return "InspectionDescriptionNotFoundInspection";
}
@Override
@@ -0,0 +1,130 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.idea.devkit.inspections;
import com.intellij.codeInspection.InspectionManager;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.devkit.inspections.quickfix.CreateHtmlDescriptionFix;
import org.jetbrains.idea.devkit.util.PsiUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author Konstantin Bulenkov
*/
public class IntentionDescriptionNotFoundInspection extends DevKitInspectionBase{
@NonNls private static final String INTENTION = "com.intellij.codeInsight.intention.IntentionAction";
@NonNls private static final String INSPECTION_DESCRIPTIONS = "intentionDescriptions";
@Override
public ProblemDescriptor[] checkClass(@NotNull PsiClass aClass, @NotNull InspectionManager manager, boolean isOnTheFly) {
final Project project = aClass.getProject();
final PsiIdentifier nameIdentifier = aClass.getNameIdentifier();
final Module module = ModuleUtil.findModuleForPsiElement(aClass);
if (nameIdentifier == null || module == null || !PsiUtil.isInstanciatable(aClass)) return null;
final PsiClass base = JavaPsiFacade.getInstance(project).findClass(INTENTION, GlobalSearchScope.allScope(project));
if (base == null || ! aClass.isInheritor(base, true)) return null;
final PsiMethod method = findNearestMethod("getFamilyName", aClass);
if (method == null) return null;
final String filename = PsiUtil.getReturnedLiteral(method, aClass);
if (filename == null) return null;
for (PsiDirectory description : getIntentionDescriptionsDirs(module)) {
PsiDirectory dir = description.findSubdirectory(filename);
if (dir == null) dir = description.findSubdirectory(aClass.getName());
if (dir == null) continue;
final PsiFile descr = dir.findFile("description.html");
if (descr != null) return null;
}
final PsiElement problem = aClass.getNameIdentifier();
final ProblemDescriptor problemDescriptor = manager
.createProblemDescriptor(problem == null ? nameIdentifier : problem,
"Intention does not have a description", isOnTheFly, new LocalQuickFix[]{new CreateHtmlDescriptionFix(aClass.getName(), module, true)},
ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
return new ProblemDescriptor[]{problemDescriptor};
}
public static List<VirtualFile> getPotentialRoots(Module module) {
final PsiDirectory[] dirs = getIntentionDescriptionsDirs(module);
final List<VirtualFile> result = new ArrayList<VirtualFile>();
if (dirs.length != 0) {
for (PsiDirectory dir : dirs) {
final PsiDirectory parent = dir.getParentDirectory();
if (parent != null) result.add(parent.getVirtualFile());
}
} else {
result.addAll(Arrays.asList(ModuleRootManager.getInstance(module).getSourceRoots()));
}
return result;
}
public static PsiDirectory[] getIntentionDescriptionsDirs(Module module) {
final PsiPackage aPackage = JavaPsiFacade.getInstance(module.getProject()).findPackage(INSPECTION_DESCRIPTIONS);
if (aPackage != null) {
return aPackage.getDirectories(GlobalSearchScope.moduleWithDependenciesScope(module));
} else {
return PsiDirectory.EMPTY_ARRAY;
}
}
@Nullable
private static PsiMethod findNearestMethod(String name, @Nullable PsiClass cls) {
if (cls == null) return null;
for (PsiMethod method : cls.getMethods()) {
if (method.getParameterList().getParametersCount() == 0 && method.getName().equals(name)) {
return method.getModifierList().hasModifierProperty(PsiModifier.ABSTRACT) ? null : method;
}
}
return findNearestMethod(name, cls.getSuperClass());
}
@Nls
@NotNull
public String getDisplayName() {
return "Intention Description Checker";
}
@NotNull
public String getShortName() {
return "IntentionDescriptionNotFoundInspection";
}
@Override
public boolean isEnabledByDefault() {
return true;
}
}
@@ -42,7 +42,8 @@ import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.devkit.DevKitBundle;
import org.jetbrains.idea.devkit.inspections.DescriptionNotFoundInspection;
import org.jetbrains.idea.devkit.inspections.InspectionDescriptionNotFoundInspection;
import org.jetbrains.idea.devkit.inspections.IntentionDescriptionNotFoundInspection;
import javax.swing.*;
import java.io.File;
@@ -54,14 +55,15 @@ import java.util.List;
*/
public class CreateHtmlDescriptionFix implements LocalQuickFix, Iconable {
private final String myFilename;
private final Module myModule;
@NonNls private static final String DESCRIPTIONS_FOLDER = "inspectionDescriptions";
private final Module myModule;
@NonNls private static final String TEMPLATE_NAME = "InspectionDescription.html";
private static final Icon NEW_HTML_ICON = IconLoader.getIcon("/new_html.png");
private final boolean isIntention;
public CreateHtmlDescriptionFix(String filename, Module module) {
public CreateHtmlDescriptionFix(String filename, Module module, boolean isIntention) {
myModule = module;
myFilename = filename + ".html";
this.isIntention = isIntention;
myFilename = isIntention ? filename : filename + ".html";
}
@NotNull
@@ -75,7 +77,10 @@ public class CreateHtmlDescriptionFix implements LocalQuickFix, Iconable {
}
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final List<VirtualFile> virtualFiles = DescriptionNotFoundInspection.getPotentialRoots(myModule);
final List<VirtualFile> virtualFiles = isIntention ?
IntentionDescriptionNotFoundInspection.getPotentialRoots(myModule)
:
InspectionDescriptionNotFoundInspection.getPotentialRoots(myModule);
final VirtualFile[] roots = prepare(VfsUtil.toVirtualFileArray(virtualFiles));
if (roots.length == 1) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@@ -88,7 +93,11 @@ public class CreateHtmlDescriptionFix implements LocalQuickFix, Iconable {
else {
List<String> options = new ArrayList<String>();
for (VirtualFile file : roots) {
options.add(file.getPresentableUrl() + File.separator + DESCRIPTIONS_FOLDER + File.separator + myFilename);
String path = file.getPresentableUrl() + File.separator + getDescriptionFolderName() + File.separator + myFilename;
if (isIntention) {
path += File.separator + "description.html";
}
options.add(path);
}
final JList files = new JBList(ArrayUtil.toStringArray(options));
final PopupChooserBuilder builder = JBPopupFactory.getInstance().createListPopupBuilder(files);
@@ -117,16 +126,22 @@ public class CreateHtmlDescriptionFix implements LocalQuickFix, Iconable {
PsiDirectory descrRoot = null;
if (psiRoot == null) return;
for (PsiDirectory dir : psiRoot.getSubdirectories()) {
if (DESCRIPTIONS_FOLDER.equals(dir.getName())) {
if (getDescriptionFolderName().equals(dir.getName())) {
descrRoot = dir;
break;
}
}
try {
descrRoot = descrRoot == null ? psiRoot.createSubdirectory(DESCRIPTIONS_FOLDER) : descrRoot;
descrRoot = descrRoot == null ? psiRoot.createSubdirectory(getDescriptionFolderName()) : descrRoot;
if (isIntention) {
PsiDirectory dir = descrRoot.findSubdirectory(myFilename);
if (dir == null) {
descrRoot = descrRoot.createSubdirectory(myFilename);
}
}
final FileTemplate descrTemplate = FileTemplateManager.getInstance().getJ2eeTemplate(TEMPLATE_NAME);
final PsiElement template = FileTemplateUtil.createFromTemplate(descrTemplate, myFilename, null, descrRoot);
final PsiElement template = FileTemplateUtil.createFromTemplate(descrTemplate, isIntention? "description.html" : myFilename, null, descrRoot);
if (template instanceof PsiFile) {
final VirtualFile file = ((PsiFile)template).getVirtualFile();
if (file != null) {
@@ -142,7 +157,7 @@ public class CreateHtmlDescriptionFix implements LocalQuickFix, Iconable {
return NEW_HTML_ICON;
}
private static VirtualFile[] prepare(VirtualFile[] roots) {
private VirtualFile[] prepare(VirtualFile[] roots) {
List<VirtualFile> found = new ArrayList<VirtualFile>();
for (VirtualFile root : roots) {
if (containsDescriptionDir(root)) {
@@ -152,13 +167,17 @@ public class CreateHtmlDescriptionFix implements LocalQuickFix, Iconable {
return found.size() > 0 ? VfsUtil.toVirtualFileArray(found) : roots;
}
private static boolean containsDescriptionDir(VirtualFile root) {
private boolean containsDescriptionDir(VirtualFile root) {
if (!root.isDirectory()) return false;
for (VirtualFile file : root.getChildren()) {
if (file.isDirectory() && DESCRIPTIONS_FOLDER.equals(file.getName())) {
if (file.isDirectory() && getDescriptionFolderName().equals(file.getName())) {
return true;
}
}
return false;
}
private String getDescriptionFolderName() {
return isIntention ? "intentionDescriptions" : "inspectionDescriptions";
}
}