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

This commit is contained in:
Kirill Likhodedov
2010-07-12 13:38:15 +04:00
488 changed files with 131589 additions and 504 deletions
+1
View File
@@ -11,6 +11,7 @@
<module fileurl="file://$PROJECT_DIR$/RegExpSupport/RegExpSupport.iml" filepath="$PROJECT_DIR$/RegExpSupport/RegExpSupport.iml" />
<module fileurl="file://$PROJECT_DIR$/platform/annotations/annotations.iml" filepath="$PROJECT_DIR$/platform/annotations/annotations.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/plugins/ant/ant.iml" filepath="$PROJECT_DIR$/plugins/ant/ant.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/relaxng/relaxng.iml" filepath="$PROJECT_DIR$/plugins/relaxng/relaxng.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/platform/boot/boot.iml" filepath="$PROJECT_DIR$/platform/boot/boot.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/bootstrap/bootstrap.iml" filepath="$PROJECT_DIR$/platform/bootstrap/bootstrap.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/build/build.iml" filepath="$PROJECT_DIR$/build/build.iml" />
+3
View File
@@ -172,6 +172,9 @@ def layoutFull(String home, String targetDirectory) {
layoutPlugin("SpellChecker", "spellchecker", "spellchecker-core")
layoutPlugin("RelaxNG-Support", "relaxng") {
fileset(dir: "${home}/community/plugins/relaxng/lib", includes: "**/*.jar")
}
layoutPlugin("maven") {
jar("maven-facade-api.jar") {
@@ -97,6 +97,8 @@ import java.util.concurrent.TimeUnit;
public class CompileDriver {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.CompileDriver");
// to be used in tests only for debug output
public static boolean ourDebugMode = false;
private final Project myProject;
private final Map<Pair<IntermediateOutputCompiler, Module>, Pair<VirtualFile, VirtualFile>> myGenerationCompilerModuleToOutputDirMap; // [IntermediateOutputCompiler, Module] -> [ProductionSources, TestSources]
@@ -1558,12 +1560,20 @@ public class CompileDriver {
if (toDelete.isEmpty() && toCompile.isEmpty()) {
return false;
}
if (LOG.isDebugEnabled()) {
if (LOG.isDebugEnabled() || ourDebugMode) {
if (!toDelete.isEmpty()) {
LOG.debug("Found items to delete, compiler " + compiler.getDescription());
final String message = "Found items to delete, compiler " + compiler.getDescription();
LOG.debug(message);
if (ourDebugMode) {
System.out.println(message);
}
}
if (!toCompile.isEmpty()) {
LOG.debug("Found items to compile, compiler " + compiler.getDescription());
final String message = "Found items to compile, compiler " + compiler.getDescription();
LOG.debug(message);
if (ourDebugMode) {
System.out.println(message);
}
}
}
throw new ExitException(ExitStatus.CANCELLED);
@@ -78,6 +78,7 @@ import java.util.*;
public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.TranslatingCompilerFilesMonitor");
public static boolean ourDebugMode = false;
@NonNls
private static final String PATHS_TO_DELETE_FILENAME = "paths_to_delete.dat";
private static final String OUTPUT_ROOTS_FILENAME = "output_roots.dat";
@@ -163,8 +164,12 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
while (scopeSrcIterator.hasNext()) {
final VirtualFile file = scopeSrcIterator.next();
if (!file.isValid()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Skipping invalid file " + file.getPresentableUrl());
if (LOG.isDebugEnabled() || ourDebugMode) {
final String message = "Skipping invalid file " + file.getPresentableUrl();
LOG.debug(message);
if (ourDebugMode) {
System.out.println(message);
}
}
continue;
}
@@ -212,11 +217,22 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
//noinspection UnnecessaryBoxing
final File file = new File(outputPath);
toDelete.add(new Trinity<File, String, Boolean>(file, classNamePair.getClassName(), Boolean.valueOf(sourcePresent)));
if (LOG.isDebugEnabled()) {
LOG.debug("Found file to delete: " + file);
if (LOG.isDebugEnabled() || ourDebugMode) {
final String message = "Found file to delete: " + file;
LOG.debug(message);
if (ourDebugMode) {
System.out.println(message);
}
}
}
else {
if (LOG.isDebugEnabled() || ourDebugMode) {
final String message = "Found zombie entry marked for deletion: " + outputPath;
LOG.debug(message);
if (ourDebugMode) {
System.out.println(message);
}
}
// must be gagbage entry, should cleanup
zombieEntries.add(outputPath);
}
@@ -301,8 +317,12 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
final long fileStamp = file.getTimeStamp();
info.updateTimestamp(projectId, fileStamp);
saveSourceInfo(file, info);
if (LOG.isDebugEnabled()) {
LOG.debug("Unschedule recompilation (successfully compiled) " + file.getPresentableUrl());
if (LOG.isDebugEnabled() || ourDebugMode) {
final String message = "Unschedule recompilation (successfully compiled) " + file.getPresentableUrl();
LOG.debug(message);
if (ourDebugMode) {
System.out.println(message);
}
}
removeSourceForRecompilation(projectId, Math.abs(getFileId(file)));
if ((fileStamp > compilationStartStamp && !((CompileContextEx)context).isGenerated(file)) || forceRecompile.contains(file)) {
@@ -365,8 +385,12 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
final String outputPath = FileUtil.toSystemIndependentName(CompilerIOUtil.readString(is));
final String srcUrl = CompilerIOUtil.readString(is);
final String className = CompilerIOUtil.readString(is);
if (LOG.isDebugEnabled()) {
LOG.debug("INIT path to delete: " + outputPath);
if (LOG.isDebugEnabled() || ourDebugMode) {
final String message = "INIT path to delete: " + outputPath;
LOG.debug(message);
if (ourDebugMode) {
System.out.println(message);
}
}
map.put(outputPath, new SourceUrlClassNamePair(srcUrl, className));
}
@@ -1136,8 +1160,12 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
public void beforeFileDeletion(final VirtualFileEvent event) {
final VirtualFile eventFile = event.getFile();
if (LOG.isDebugEnabled() && eventFile.isDirectory()) {
LOG.debug("Processing file deletion: " + eventFile.getPresentableUrl());
if ((LOG.isDebugEnabled() && eventFile.isDirectory()) || ourDebugMode) {
final String message = "Processing file deletion: " + eventFile.getPresentableUrl();
LOG.debug(message);
if (ourDebugMode) {
System.out.println(message);
}
}
processRecursively(eventFile, true, new FileProcessor() {
public void execute(final VirtualFile file) {
@@ -1167,8 +1195,12 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
for (int projectId : projects.toArray()) {
// mark associated outputs for deletion
srcInfo.processOutputPaths(projectId, deletionProc);
if (LOG.isDebugEnabled()) {
LOG.debug("Unschedule recompilation because of deletion " + file.getPresentableUrl());
if (LOG.isDebugEnabled() || ourDebugMode) {
final String message = "Unschedule recompilation because of deletion " + file.getPresentableUrl();
LOG.debug(message);
if (ourDebugMode) {
System.out.println(message);
}
}
removeSourceForRecompilation(projectId, Math.abs(getFileId(file)));
}
@@ -1269,8 +1301,12 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
mySourcesToRecompile.put(projectId, set);
}
alreadyMarked = !set.add(Math.abs(getFileId(srcFile)));
if (!alreadyMarked && LOG.isDebugEnabled()) {
LOG.debug("Scheduled recompilation " + srcFile.getPresentableUrl());
if (!alreadyMarked && (LOG.isDebugEnabled() || ourDebugMode)) {
final String message = "Scheduled recompilation " + srcFile.getPresentableUrl();
LOG.debug(message);
if (ourDebugMode) {
System.out.println(message);
}
}
}
@@ -1336,8 +1372,12 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
myOutputsToDelete.put(projectId, map);
}
map.put(outputPath, new SourceUrlClassNamePair(srcUrl, classname));
if (LOG.isDebugEnabled()) {
LOG.debug("ADD path to delete: " + outputPath + "; source: " + srcUrl);
if (LOG.isDebugEnabled() || ourDebugMode) {
final String message = "ADD path to delete: " + outputPath + "; source: " + srcUrl;
LOG.debug(message);
if (ourDebugMode) {
System.out.println(message);
}
}
}
}
@@ -1349,8 +1389,12 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
if (map != null) {
final SourceUrlClassNamePair val = map.remove(outputPath);
if (val != null) {
if (LOG.isDebugEnabled()) {
LOG.debug("REMOVE path to delete: " + outputPath);
if (LOG.isDebugEnabled() || ourDebugMode) {
final String message = "REMOVE path to delete: " + outputPath;
LOG.debug(message);
if (ourDebugMode) {
System.out.println(message);
}
}
if (map.isEmpty()) {
myOutputsToDelete.remove(projectId);
@@ -1081,7 +1081,11 @@ public class ExtractMethodProcessor implements MatchProvider {
}
if (success) {
myTargetClass = newTargetClass;
inputVariables.addAll(array);
for (PsiVariable variable : array) {
if (!inputVariables.contains(variable)) {
inputVariables.addAll(array);
}
}
myNeedChangeContext = true;
}
}
@@ -18,6 +18,7 @@ package com.intellij.refactoring.inline;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.lang.StdLanguages;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.patterns.ElementPattern;
@@ -34,6 +35,7 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.Processor;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
/**
@@ -50,17 +52,29 @@ public class InlineToAnonymousClassHandler extends JavaInlineActionHandler {
return element instanceof PsiMethod || element instanceof PsiClass;
}
public boolean canInlineElement(PsiElement element) {
public boolean canInlineElement(final PsiElement element) {
if (element.getLanguage() != StdLanguages.JAVA) return false;
if (element instanceof PsiMethod) {
PsiMethod method = (PsiMethod)element;
if (method.isConstructor() && !InlineMethodHandler.isChainingConstructor(method)) {
final PsiClass containingClass = method.getContainingClass();
return containingClass != null && ClassInheritorsSearch.search(containingClass).findAll().size() == 0;
if (containingClass == null) return false;
return findClassInheritors(containingClass);
}
}
if (!(element instanceof PsiClass)) return false;
Collection<PsiClass> inheritors = ClassInheritorsSearch.search((PsiClass)element).findAll();
if (element instanceof PsiAnonymousClass) return false;
return findClassInheritors((PsiClass)element);
}
private static boolean findClassInheritors(final PsiClass element) {
final Collection<PsiClass> inheritors = new ArrayList<PsiClass>();
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable(){
@Override
public void run() {
inheritors.addAll(ClassInheritorsSearch.search(element).findAll());
}
}, "Searching for class \"" + element.getQualifiedName() + "\" inheritors ...", true, element.getProject())) return false;
return inheritors.size() == 0;
}
@@ -78,9 +92,15 @@ public class InlineToAnonymousClassHandler extends JavaInlineActionHandler {
return;
}
String errorMessage = getCannotInlineMessage(psiClass);
if (errorMessage != null) {
CommonRefactoringUtil.showErrorHint(project, editor, errorMessage, RefactoringBundle.message("inline.to.anonymous.refactoring"), null);
final Ref<String> errorMessage = new Ref<String>();
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable(){
@Override
public void run() {
errorMessage.set(getCannotInlineMessage(psiClass));
}
}, "Check if inline is possible...", true, project)) return;
if (errorMessage.get() != null) {
CommonRefactoringUtil.showErrorHint(project, editor, errorMessage.get(), RefactoringBundle.message("inline.to.anonymous.refactoring"), null);
return;
}
@@ -29,6 +29,7 @@ import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.psi.*;
@@ -142,11 +143,17 @@ public class JavaPullUpHandler implements RefactoringActionHandler, PullUpDialog
public boolean checkConflicts(PullUpDialog dialog) {
public boolean checkConflicts(final PullUpDialog dialog) {
final MemberInfo[] infos = dialog.getSelectedMemberInfos();
PsiClass superClass = dialog.getSuperClass();
final PsiClass superClass = dialog.getSuperClass();
if (!checkWritable(superClass, infos)) return false;
MultiMap<PsiElement,String> conflicts = PullUpConflictsUtil.checkConflicts(infos, mySubclass, superClass, null, null, dialog.getContainmentVerifier());
final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
public void run() {
conflicts
.putAllValues(PullUpConflictsUtil.checkConflicts(infos, mySubclass, superClass, null, null, dialog.getContainmentVerifier()));
}
}, "Detecting possible conflicts...", true, myProject)) return false;
if (!conflicts.isEmpty()) {
ConflictsDialog conflictsDialog = new ConflictsDialog(myProject, conflicts);
conflictsDialog.show();
@@ -0,0 +1,12 @@
class Test {
void f() {
new Runnable() {
public void run() {
int j = 0;
if (j == 0 && <selection>j < 0 && j > 0</selection>) {
assert false;
}
}
};
}
}
@@ -0,0 +1,16 @@
class Test {
void f() {
new Runnable() {
public void run() {
int j = 0;
if (j == 0 && newMethod(j)) {
assert false;
}
}
};
}
private boolean newMethod(int j) {
return j < 0 && j > 0;
}
}
@@ -9,10 +9,13 @@ import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiType;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.refactoring.extractMethod.ExtractMethodProcessor;
import com.intellij.refactoring.extractMethod.PrepareFailedException;
import com.intellij.refactoring.introduceVariable.IntroduceVariableBase;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.refactoring.util.duplicates.Match;
import com.intellij.testFramework.LightCodeInsightTestCase;
import com.intellij.util.IncorrectOperationException;
@@ -448,6 +451,10 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
doDuplicatesTest();
}
public void testParametersFromAnonymous() throws Exception {
doTest();
}
private void doPrepareErrorTest(final String expectedMessage) throws Exception {
String expectedError = null;
try {
@@ -503,6 +510,12 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
else {
elements = CodeInsightUtil.findStatementsInRange(file, startOffset, endOffset);
}
if (elements.length == 0) {
final PsiExpression expression = IntroduceVariableBase.getSelectedExpression(project, file, startOffset, endOffset);
if (expression != null) {
elements = new PsiElement[]{expression};
}
}
assertTrue(elements.length > 0);
final ExtractMethodProcessor processor =
@@ -30,6 +30,7 @@ import java.util.Collection;
* @author spleaner
*/
public abstract class FileColorManager {
public static final String OUT_OF_PROJECT_SCOPE_COLOR = "OUT_OF_PROJECT_SCOPE";
public static FileColorManager getInstance(@NotNull final Project project) {
return ServiceManager.getService(project, FileColorManager.class);
@@ -41,6 +42,8 @@ public abstract class FileColorManager {
public abstract boolean isEnabledForTabs();
public abstract boolean isHighlightNonProjectFiles();
@SuppressWarnings({"MethodMayBeStatic"})
@Nullable
public abstract Color getColor(@NotNull String name);
@@ -23,14 +23,17 @@ import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
import com.intellij.openapi.editor.impl.FoldingModelImpl;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.options.CompositeConfigurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.Nls;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -57,8 +60,9 @@ public class CodeFoldingConfigurable extends CompositeConfigurable<CodeFoldingOp
public JComponent createComponent() {
for (CodeFoldingOptionsProvider provider : getConfigurables()) {
myFoldingPanel.add(provider.createComponent(), new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0, 0, GridBagConstraints.NORTHWEST,
GridBagConstraints.NONE, new Insets(0,0,0,0), 0,0));
myFoldingPanel
.add(provider.createComponent(), new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0, 0, GridBagConstraints.NORTHWEST,
GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
}
return myRootPanel;
}
@@ -72,19 +76,25 @@ public class CodeFoldingConfigurable extends CompositeConfigurable<CodeFoldingOp
EditorSettingsExternalizable.getInstance().setFoldingOutlineShown(myCbFolding.isSelected());
super.apply();
final List<Pair<Editor, Project>> toUpdate = new ArrayList<Pair<Editor, Project>>();
for (final Editor editor : EditorFactory.getInstance().getAllEditors()) {
final Project project = editor.getProject();
if (project != null && !project.isDefault()) {
final CodeFoldingManager foldingManager = CodeFoldingManager.getInstance(project);
if (foldingManager != null) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
foldingManager.forceDefaultState(editor);
}
}, ModalityState.NON_MODAL);
}
toUpdate.add(Pair.create(editor, project));
}
}
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
for (Pair<Editor, Project> each : toUpdate) {
final CodeFoldingManager foldingManager = CodeFoldingManager.getInstance(each.second);
if (foldingManager != null) {
foldingManager.buildInitialFoldings(each.first);
}
}
EditorOptionsPanel.reinitAllEditors();
}
}, ModalityState.NON_MODAL);
}
public void reset() {
@@ -87,7 +87,7 @@ public class UpdateHighlightersUtil {
List<HighlightInfo> infosToRemove = new ArrayList<HighlightInfo>();
for (HighlightInfo info : infos) {
if (info.group == group) {
manager.removeEditorAnnotation(fileEditor, info.fileLevelComponent);
manager.removeTopComponent(fileEditor, info.fileLevelComponent);
infosToRemove.add(info);
}
}
@@ -340,7 +340,7 @@ public class UpdateHighlightersUtil {
if (fileEditor instanceof TextEditor) {
FileLevelIntentionComponent component = new FileLevelIntentionComponent(info.description, info.severity, info.quickFixActionRanges,
project, psiFile, ((TextEditor)fileEditor).getEditor());
manager.showEditorAnnotation(fileEditor, component);
manager.addTopComponent(fileEditor, component);
List<HighlightInfo> fileLevelInfos = fileEditor.getUserData(FILE_LEVEL_HIGHLIGHTS);
if (fileLevelInfos == null) {
fileLevelInfos = new ArrayList<HighlightInfo>();
@@ -49,7 +49,6 @@ public class FileLevelIntentionComponent extends EditorNotificationPanel {
final HighlightSeverity severity,
final List<Pair<HighlightInfo.IntentionActionDescriptor, TextRange>> intentions,
final Project project, final PsiFile psiFile, final Editor editor) {
super();
myProject = project;
final ShowIntentionsPass.IntentionsInfo info = new ShowIntentionsPass.IntentionsInfo();
@@ -155,4 +155,8 @@ public class CustomTemplateCallback {
}
return element;
}
public boolean isInInjectedFragment() {
return myInInjectedFragment;
}
}
@@ -150,7 +150,7 @@ public class ExecutionHelper {
public static class RailsErrorViewPanel extends NewErrorTreeViewPanel {
public RailsErrorViewPanel(final Project project) {
super(project, null);
super(project, "reference.toolWindows.messages");
}
protected boolean canHideWarnings() {
@@ -270,54 +270,27 @@ public class ExecutionHelper {
final int timeout) {
return new Runnable() {
private final Semaphore mySemaphore = new Semaphore();
private final Object LOCK = new Object();
private Boolean processedFinished = Boolean.FALSE;
private final Runnable myProcessThread = new Runnable() {
public void run() {
try {
processHandler.waitFor();
synchronized (LOCK) {
processedFinished = Boolean.TRUE;
final boolean finished = processHandler.waitFor(1000 * timeout);
if (!finished) {
LOG.error("Timeout (" + timeout + " sec) on executing: " + processHandler.getCommandLine());
processHandler.destroyProcess();
}
}
finally {
} finally {
mySemaphore.up();
}
}
};
private final Runnable myTimeoutListener = new Runnable() {
public void run() {
try {
synchronized (this) {
try {
wait(1000 * timeout);
synchronized (LOCK) {
if (!processedFinished) {
LOG.error("Timeout (" + timeout + " sec) on executing: " + processHandler.getCommandLine());
processHandler.destroyProcess();
}
}
}
finally {
mySemaphore.up();
}
}
}
catch (InterruptedException e) {
//Do nothing
}
}
};
public void run() {
mySemaphore.down();
ApplicationManager.getApplication().executeOnPooledThread(myProcessThread);
ApplicationManager.getApplication().executeOnPooledThread(myTimeoutListener);
mySemaphore.waitFor();
}
};
}
}
}
@@ -100,7 +100,8 @@ public class GeneralColorsPage implements ColorSettingsPage, InspectionColorSett
private static final ColorDescriptor[] COLOR_DESCRIPTORS = {
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.background.in.readonly.files"), EditorColors.READONLY_BACKGROUND_COLOR, ColorDescriptor.Kind.BACKGROUND),
new ColorDescriptor(OptionsBundle.message("options.deneral.color.descriptor.readonly.fragment.background"), EditorColors.READONLY_FRAGMENT_BACKGROUND_COLOR, ColorDescriptor.Kind.BACKGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.gutter.background"), EditorColors.LEFT_GUTTER_BACKGROUND, ColorDescriptor.Kind.BACKGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.gutter.background"), EditorColors.GUTTER_BACKGROUND, ColorDescriptor.Kind.BACKGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.notification.background"), EditorColors.NOTIFICATION_BACKGROUND, ColorDescriptor.Kind.BACKGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.selection.background"), EditorColors.SELECTION_BACKGROUND_COLOR, ColorDescriptor.Kind.BACKGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.selection.foreground"), EditorColors.SELECTION_FOREGROUND_COLOR, ColorDescriptor.Kind.FOREGROUND),
@@ -113,8 +114,8 @@ public class GeneralColorsPage implements ColorSettingsPage, InspectionColorSett
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.line.number"), EditorColors.LINE_NUMBERS_COLOR, ColorDescriptor.Kind.FOREGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.vcs.annotations"), EditorColors.ANNOTATIONS_COLOR, ColorDescriptor.Kind.FOREGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.vcs.annotations.merged"), EditorColors.ANNOTATIONS_MERGED_COLOR, ColorDescriptor.Kind.FOREGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.folding.outline"), EditorColors.FOLDING_TREE_COLOR, ColorDescriptor.Kind.FOREGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.selected.folding.outline"), EditorColors.SELECTED_FOLDING_TREE_COLOR, ColorDescriptor.Kind.FOREGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.tearline"), EditorColors.TEARLINE_COLOR, ColorDescriptor.Kind.FOREGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.tearline.selected"), EditorColors.SELECTED_TEARLINE_COLOR, ColorDescriptor.Kind.FOREGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.added.lines"), EditorColors.ADDED_LINES_COLOR, ColorDescriptor.Kind.BACKGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.modified.lines"), EditorColors.MODIFIED_LINES_COLOR, ColorDescriptor.Kind.BACKGROUND),
new ColorDescriptor(OptionsBundle.message("options.java.color.descriptor.method.separator.color"), CodeInsightColors.METHOD_SEPARATORS_COLOR, ColorDescriptor.Kind.FOREGROUND),
@@ -32,12 +32,13 @@ import com.intellij.refactoring.rename.PsiElementRenameHandler;
import com.intellij.refactoring.rename.RenameHandler;
import com.intellij.refactoring.rename.RenameHandlerRegistry;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public final class VariableInplaceRenameHandler implements RenameHandler {
public class VariableInplaceRenameHandler implements RenameHandler {
private static final ThreadLocal<Boolean> ourPreventInlineRenameFlag = new ThreadLocal<Boolean>();
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler");
public boolean isAvailableOnDataContext(final DataContext dataContext) {
public final boolean isAvailableOnDataContext(final DataContext dataContext) {
final PsiElement element = PsiElementRenameHandler.getElement(dataContext);
final Editor editor = PlatformDataKeys.EDITOR.getData(dataContext);
final PsiFile file = LangDataKeys.PSI_FILE.getData(dataContext);
@@ -46,15 +47,20 @@ public final class VariableInplaceRenameHandler implements RenameHandler {
if (ourPreventInlineRenameFlag.get() != null) {
return false;
}
return isAvailable(element, editor, file);
}
protected boolean isAvailable(PsiElement element, Editor editor, PsiFile file) {
final PsiElement nameSuggestionContext = file.findElementAt(editor.getCaretModel().getOffset());
final RefactoringSupportProvider supportProvider = element != null ? LanguageRefactoringSupport.INSTANCE.forLanguage(element.getLanguage()):null;
final RefactoringSupportProvider
supportProvider = element != null ? LanguageRefactoringSupport.INSTANCE.forLanguage(element.getLanguage()):null;
return supportProvider != null &&
editor.getSettings().isVariableInplaceRenameEnabled() &&
supportProvider.doInplaceRenameFor(element, nameSuggestionContext);
}
public boolean isRenaming(final DataContext dataContext) {
public final boolean isRenaming(final DataContext dataContext) {
return isAvailableOnDataContext(dataContext);
}
@@ -83,7 +89,8 @@ public final class VariableInplaceRenameHandler implements RenameHandler {
return;
}
final boolean startedRename = new VariableInplaceRenamer((PsiNameIdentifierOwner)elementToRename, editor).performInplaceRename();
VariableInplaceRenamer renamer = createRenamer(elementToRename, editor);
boolean startedRename = renamer == null ? false : renamer.performInplaceRename();
if (!startedRename) {
try {
@@ -101,4 +108,9 @@ public final class VariableInplaceRenameHandler implements RenameHandler {
}
}
}
@Nullable
protected VariableInplaceRenamer createRenamer(PsiElement elementToRename, Editor editor) {
return new VariableInplaceRenamer((PsiNameIdentifierOwner)elementToRename, editor);
}
}
@@ -16,6 +16,8 @@
package com.intellij.ui.tabs;
import com.intellij.openapi.project.Project;
import com.intellij.psi.search.scope.packageSet.NamedScopeManager;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -54,7 +56,7 @@ class FileColorConfiguration implements Cloneable {
myColorName = colorName;
}
public boolean isValid() {
public boolean isValid(Project project) {
if (myScopeName == null || myScopeName.length() == 0) {
return false;
}
@@ -63,11 +65,15 @@ class FileColorConfiguration implements Cloneable {
return false;
}
return true;
if (project != null) {
return NamedScopeManager.getScope(project, myScopeName) != null;
} else {
return true;
}
}
public void save(@NotNull final Element e) {
if (!isValid()) {
if (!isValid(null)) {
return;
}
@@ -53,11 +53,14 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent
private final Project myProject;
private boolean myEnabledForTabs = true;
private boolean myHighlightNonProjectFiles = true;
private static final Map<String, Color> ourDefaultColors;
private static final Map<String, Color> ourHiddenColors;
static {
ourDefaultColors = new LinkedHashMap<String, Color>();
ourHiddenColors = new LinkedHashMap<String, Color>();
ourDefaultColors.put("Blue", new Color(215, 237, 243));
//ourDefaultColors.put("Blue 2", new Color(218, 224, 244));
ourDefaultColors.put("Green", new Color(228, 241, 209));
@@ -66,6 +69,8 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent
ourDefaultColors.put("Rose", new Color(242, 206, 202));
ourDefaultColors.put("Violet", new Color(222, 213, 241));
ourDefaultColors.put("Yellow", new Color(247, 241, 203));
ourHiddenColors.put(OUT_OF_PROJECT_SCOPE_COLOR, new Color(255, 255, 228));
}
public FileColorManagerImpl(@NotNull final Project project) {
@@ -95,11 +100,20 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent
return myEnabledForTabs;
}
public boolean isHighlightNonProjectFiles() {
return myHighlightNonProjectFiles;
}
public void setHighlightNonProjectFiles(boolean highlight) {
myHighlightNonProjectFiles = highlight;
}
public Element getState(final boolean shared) {
Element element = new Element("state");
if (!shared) {
element.setAttribute("enabled", Boolean.toString(myEnabled));
element.setAttribute("enabledForTabs", Boolean.toString(myEnabledForTabs));
element.setAttribute("highlightNonProjectFiles", Boolean.toString(myHighlightNonProjectFiles));
}
myModel.save(element, shared);
@@ -110,7 +124,8 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent
@SuppressWarnings({"MethodMayBeStatic"})
@Nullable
public Color getColor(@NotNull final String name) {
return ourDefaultColors.get(name);
final Color color = ourDefaultColors.get(name);
return color == null ? ourHiddenColors.get(name) : color;
}
public static String toString(final Color color) {
@@ -133,7 +148,10 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent
myEnabled = enabled == null ? true : Boolean.valueOf(enabled);
final String enabledForTabs = state.getAttributeValue("enabledForTabs");
myEnabledForTabs = enabledForTabs == null ? false : Boolean.valueOf(enabledForTabs);
myEnabledForTabs = enabledForTabs == null ? true : Boolean.valueOf(enabledForTabs);
final String highlightNonProjectFiles = state.getAttributeValue("highlightNonProjectFiles");
myHighlightNonProjectFiles = highlightNonProjectFiles == null ? true : Boolean.valueOf(highlightNonProjectFiles);
}
myModel.load(state, shared);
@@ -183,7 +201,7 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent
@Nullable
public Color getFileColor(@NotNull final PsiFile file) {
final String colorName = myModel.getColor(file);
return colorName == null ? null : ourDefaultColors.get(colorName);
return colorName == null ? null : getColor(colorName);
}
public boolean isShared(@NotNull final String scopeName) {
@@ -37,6 +37,7 @@ public class FileColorsConfigurablePanel extends JPanel implements Disposable {
private FileColorManagerImpl myManager;
private final JCheckBox myEnabledCheckBox;
private final JCheckBox myTabsEnabledCheckBox;
private final JCheckBox myHighlightNonProjectFilesCheckBox;
private final FileColorSettingsTable myLocalTable;
private final FileColorSettingsTable mySharedTable;
@@ -56,6 +57,10 @@ public class FileColorsConfigurablePanel extends JPanel implements Disposable {
myTabsEnabledCheckBox = new JCheckBox("Use colors in Editor Tabs");
myTabsEnabledCheckBox.setMnemonic('T');
topPanel.add(myTabsEnabledCheckBox);
myHighlightNonProjectFilesCheckBox = new JCheckBox("Highlight Non-Project Files");
myHighlightNonProjectFilesCheckBox.setMnemonic('N');
topPanel.add(myHighlightNonProjectFilesCheckBox);
topPanel.add(Box.createHorizontalGlue());
add(topPanel, BorderLayout.NORTH);
@@ -229,6 +234,7 @@ public class FileColorsConfigurablePanel extends JPanel implements Disposable {
modified = myEnabledCheckBox.isSelected() != myManager.isEnabled();
modified |= myTabsEnabledCheckBox.isSelected() != myManager.isEnabledForTabs();
modified |= myHighlightNonProjectFilesCheckBox.isSelected() != myManager.isHighlightNonProjectFiles();
modified |= myLocalTable.isModified() || mySharedTable.isModified();
return modified;
@@ -237,6 +243,7 @@ public class FileColorsConfigurablePanel extends JPanel implements Disposable {
public void apply() {
myManager.setEnabled(myEnabledCheckBox.isSelected());
myManager.setEnabledForTabs(myTabsEnabledCheckBox.isSelected());
myManager.setHighlightNonProjectFiles(myHighlightNonProjectFilesCheckBox.isSelected());
myLocalTable.apply();
mySharedTable.apply();
@@ -247,6 +254,7 @@ public class FileColorsConfigurablePanel extends JPanel implements Disposable {
public void reset() {
myEnabledCheckBox.setSelected(myManager.isEnabled());
myTabsEnabledCheckBox.setSelected(myManager.isEnabledForTabs());
myHighlightNonProjectFilesCheckBox.setSelected(myManager.isHighlightNonProjectFiles());
if(myLocalTable.isModified()) myLocalTable.reset();
if(mySharedTable.isModified()) mySharedTable.reset();
@@ -17,10 +17,14 @@
package com.intellij.ui.tabs;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.search.scope.packageSet.NamedScope;
import com.intellij.psi.search.scope.packageSet.NamedScopeManager;
import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
import com.intellij.ui.FileColorManager;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -136,13 +140,23 @@ public class FileColorsModel implements Cloneable {
}
final FileColorConfiguration configuration = findConfiguration(psiFile);
if (configuration != null && configuration.isValid()) {
if (configuration != null && configuration.isValid(psiFile.getProject())) {
return configuration.getColorName();
}
if (FileColorManager.getInstance(myProject).isHighlightNonProjectFiles()
&& !isFileUnderProject(psiFile.getVirtualFile())) {
return FileColorManager.OUT_OF_PROJECT_SCOPE_COLOR;
}
return null;
}
private boolean isFileUnderProject(@Nullable VirtualFile file) {
if (file == null) return false;
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
return myProject.isInitialized() && !fileIndex.isIgnored(file) && fileIndex.getContentRootForFile(file) != null;
}
@Nullable
private FileColorConfiguration findConfiguration(@NotNull final PsiFile colored) {
for (final FileColorConfiguration configuration : myConfigurations) {
@@ -33,15 +33,22 @@ public interface EditorColors {
TextAttributesKey SEARCH_RESULT_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("SEARCH_RESULT_ATTRIBUTES");
TextAttributesKey WRITE_SEARCH_RESULT_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("WRITE_SEARCH_RESULT_ATTRIBUTES");
TextAttributesKey IDENTIFIER_UNDER_CARET_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("IDENTIFIER_UNDER_CARET_ATTRIBUTES");
TextAttributesKey WRITE_IDENTIFIER_UNDER_CARET_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("WRITE_IDENTIFIER_UNDER_CARET_ATTRIBUTES");
TextAttributesKey WRITE_IDENTIFIER_UNDER_CARET_ATTRIBUTES =
TextAttributesKey.createTextAttributesKey("WRITE_IDENTIFIER_UNDER_CARET_ATTRIBUTES");
TextAttributesKey TEXT_SEARCH_RESULT_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("TEXT_SEARCH_RESULT_ATTRIBUTES");
TextAttributesKey FOLDED_TEXT_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("FOLDED_TEXT_ATTRIBUTES");
ColorKey FOLDING_TREE_COLOR = ColorKey.createColorKey("FOLDING_TREE_COLOR");
ColorKey SELECTED_FOLDING_TREE_COLOR = ColorKey.createColorKey("SELECTED_FOLDING_TREE_COLOR");
ColorKey GUTTER_BACKGROUND = ColorKey.createColorKey("GUTTER_BACKGROUND");
@Deprecated ColorKey LEFT_GUTTER_BACKGROUND = GUTTER_BACKGROUND;
ColorKey NOTIFICATION_BACKGROUND = ColorKey.createColorKey("NOTIFICATION_BACKGROUND");
ColorKey TEARLINE_COLOR = ColorKey.createColorKey("TEARLINE_COLOR");
ColorKey SELECTED_TEARLINE_COLOR = ColorKey.createColorKey("SELECTED_TEARLINE_COLOR");
@Deprecated ColorKey FOLDING_TREE_COLOR = TEARLINE_COLOR;
@Deprecated ColorKey SELECTED_FOLDING_TREE_COLOR = SELECTED_TEARLINE_COLOR;
ColorKey ADDED_LINES_COLOR = ColorKey.createColorKey("ADDED_LINES_COLOR");
ColorKey MODIFIED_LINES_COLOR = ColorKey.createColorKey("MODIFIED_LINES_COLOR");
ColorKey LEFT_GUTTER_BACKGROUND = ColorKey.createColorKey("LEFT_GUTTER_BACKGROUND");
TextAttributesKey INJECTED_LANGUAGE_FRAGMENT = TextAttributesKey.createTextAttributesKey("INJECTED_LANGUAGE_FRAGMENT");
}
@@ -108,7 +108,13 @@ public abstract class FileEditorManager {
*/
@NotNull public abstract FileEditor[] getAllEditors();
/**
* @deprecated use addTopComponent
*/
public abstract void showEditorAnnotation(@NotNull FileEditor editor, @NotNull JComponent annotationComoponent);
/**
* @deprecated use removeTopComponent
*/
public abstract void removeEditorAnnotation(@NotNull FileEditor editor, @NotNull JComponent annotationComoponent);
public abstract void addTopComponent(@NotNull final FileEditor editor, @NotNull final JComponent component);
@@ -20,6 +20,9 @@ import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import org.jetbrains.annotations.NonNls;
import javax.swing.*;
@@ -31,19 +34,16 @@ import java.awt.*;
* @author Dmitry Avdeev
*/
public class EditorNotificationPanel extends JPanel {
protected final JLabel myLabel = new JLabel();
protected final JPanel myLinksPanel;
public EditorNotificationPanel() {
super(new BorderLayout());
setBackground(LightColors.YELLOW);
setBorder(new SideBorder(Color.gray, SideBorder.BOTTOM, true));
setBorder(BorderFactory.createEmptyBorder(1, 15, 1, 15));
setPreferredSize(new Dimension(-1, 24));
add(myLabel, BorderLayout.CENTER);
myLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
myLinksPanel = new JPanel(new FlowLayout());
myLinksPanel.setBackground(LightColors.YELLOW);
@@ -54,6 +54,12 @@ public class EditorNotificationPanel extends JPanel {
myLabel.setText(text);
}
@Override
public Color getBackground() {
Color color = EditorColorsManager.getInstance().getGlobalScheme().getColor(EditorColors.NOTIFICATION_BACKGROUND);
return color == null ? new Color(0xffffcc) : color;
}
public HyperlinkLabel createActionLabel(final String text, @NonNls final String actionId) {
return createActionLabel(text, new Runnable() {
public void run() {
@@ -63,7 +69,7 @@ public class EditorNotificationPanel extends JPanel {
}
public HyperlinkLabel createActionLabel(final String text, final Runnable action) {
HyperlinkLabel label = new HyperlinkLabel(text, Color.BLUE, LightColors.YELLOW, Color.BLUE);
HyperlinkLabel label = new HyperlinkLabel(text, Color.BLUE, getBackground(), Color.BLUE);
label.addHyperlinkListener(new HyperlinkListener() {
public void hyperlinkUpdate(final HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
@@ -85,6 +85,6 @@ public class ExcludingTraversalPolicy extends FocusTraversalPolicy {
@Override
public Component getDefaultComponent(Container aContainer) {
return myWrappee.getDefaultComponent(aContainer);
return getFirstComponent(aContainer);
}
}
@@ -114,7 +114,7 @@ public class EditorFragmentComponent extends JPanel {
setLayout(new BorderLayout());
add(component);
final Color borderColor = editor.getColorsScheme().getColor(EditorColors.SELECTED_FOLDING_TREE_COLOR);
final Color borderColor = editor.getColorsScheme().getColor(EditorColors.SELECTED_TEARLINE_COLOR);
Border outsideBorder = BorderFactory.createLineBorder(borderColor, 1);
Border insideBorder = BorderFactory.createEmptyBorder(2, 2, 2, 2);
@@ -31,7 +31,14 @@ public abstract class EditorGutterComponentEx extends JComponent implements Edit
public abstract int getWhitespaceSeparatorOffset();
public abstract Color getFoldingColor(boolean isActive);
public abstract Color getOutlineColor(boolean isActive);
/**
* @deprecated use getOutlineColor
*/
public Color getFoldingColor(boolean isActive) {
return getOutlineColor(isActive);
}
public abstract void revalidateMarkup();
@@ -0,0 +1,33 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.editor.ex;
/**
* Defines a contract for the callbacks for soft wraps management notifications (addition/removal).
*
* @author Denis Zhdanov
* @since Jul 8, 2010 6:50:17 PM
*/
public interface SoftWrapChangeListener {
/**
* This method is assumed to be called every time number of soft wraps registered for the target logical line(s)
* is changed (soft wraps are added or remove).
*
* @param changedLogicalLine logical line for which number of registered soft wraps is changed
*/
void softWrapsStateChanged(int changedLogicalLine);
}
@@ -23,6 +23,7 @@ import com.intellij.openapi.editor.impl.softwrap.SoftWrapDrawingType;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.util.Collections;
import java.util.List;
/**
@@ -72,6 +73,18 @@ public interface SoftWrapModelEx extends SoftWrapModel {
*/
List<? extends TextChange> getRegisteredSoftWraps();
/**
* Tries to find index of the target soft wrap at {@link #getRegisteredSoftWraps() soft wraps collection}.
* <code>'Target'</code> soft wrap is the one that starts at the given offset.
*
* @param offset target offset
* @return index that conforms to {@link Collections#binarySearch(List, Object)} contract, i.e. non-negative returned
* index points to soft wrap that starts at the given offset; <code>'-(negative value) - 1'</code> points
* to position at {@link #getRegisteredSoftWraps() soft wraps collection} where soft wrap for the given index
* should be inserted
*/
int getSoftWrapIndex(int offset);
/**
* Asks to paint drawing of target type at the given graphics buffer at the given position.
*
@@ -91,4 +104,12 @@ public interface SoftWrapModelEx extends SoftWrapModel {
* @return width in pixels required for the painting of the given type
*/
int getMinDrawingWidth(@NotNull SoftWrapDrawingType drawingType);
/**
* Registers given listener within the current model
*
* @param listener listener to register
* @return <code>true</code> if given listener was not registered before; <code>false</code> otherwise
*/
boolean addSoftWrapChangeListener(@NotNull SoftWrapChangeListener listener);
}
@@ -27,7 +27,6 @@ package com.intellij.openapi.editor.impl;
import com.intellij.codeInsight.hint.TooltipController;
import com.intellij.codeInsight.hint.TooltipGroup;
import com.intellij.ide.IdeEventQueue;
import com.intellij.ide.ui.LafManager;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
@@ -119,6 +118,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
public void reinitSettings() {
myBackgroundColor = null;
revalidateMarkup();
repaint();
}
@@ -191,9 +191,12 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
private void paintAnnotations(Graphics g, Rectangle clip) {
paintBackground(g, clip, getAnnotationsAreaOffset(), getAnnotationsAreaWidth());
int x = getAnnotationsAreaOffset();
int w = getAnnotationsAreaWidth();
if (w == 0) return;
paintBackground(g, clip, getAnnotationsAreaOffset(), w);
Color color = myEditor.getColorsScheme().getColor(EditorColors.ANNOTATIONS_COLOR);
g.setColor(color != null ? color : Color.blue);
@@ -201,6 +204,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
for (int i = 0; i < myTextAnnotationGutters.size(); i++) {
TextAnnotationGutterProvider gutterProvider = myTextAnnotationGutters.get(i);
int lineHeight = myEditor.getLineHeight();
int startLineNumber = clip.y / lineHeight;
int endLineNumber = (clip.y + clip.height) / lineHeight + 1;
@@ -209,7 +213,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
.line;
endLineNumber = Math.min(endLineNumber, lastLine + 1);
if (startLineNumber >= endLineNumber) {
return;
break;
}
for (int j = startLineNumber; j < endLineNumber; j++) {
@@ -219,7 +223,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
final Color bg = gutterProvider.getBgColor(logLine, myEditor);
if (bg != null) {
g.setColor(bg);
g.fillRect(x, j * lineHeight, getAnnotationsAreaWidth(), lineHeight);
g.fillRect(x, j * lineHeight, w, lineHeight);
}
g.setColor(myEditor.getColorsScheme().getColor(gutterProvider.getColor(logLine, myEditor)));
g.setFont(myEditor.getColorsScheme().getFont(style));
@@ -230,6 +234,8 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
x += myTextAnnotationGutterSizes.get(i);
}
UIUtil.drawVDottedLine((Graphics2D)g, getAnnotationsAreaOffset() + w - 1, clip.y, clip.y + clip.height, null, getOutlineColor(false));
}
private void paintFoldingTree(Graphics g, Rectangle clip) {
@@ -237,9 +243,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
paintFoldingTree((Graphics2D)g);
}
else {
g.setColor(Color.white);
int x = getWhitespaceSeparatorOffset() - 1;
UIUtil.drawVDottedLine((Graphics2D)g, x, clip.y, clip.y + clip.height, myEditor.getBackgroundColor(), getFoldingColor(false));
UIUtil.drawVDottedLine((Graphics2D)g, clip.x + clip.width -1, clip.y, clip.y + clip.height, null, getOutlineColor(false));
}
}
@@ -270,28 +274,16 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
private void paintLineNumbers(Graphics g, Rectangle clip) {
if (isLineNumbersShown()) {
paintBackground(g, clip, getLineNumberAreaOffset(), getLineNumberAreaWidth());
g.setColor(Color.white);
int x = getLineNumberAreaOffset() + getLineNumberAreaWidth() - 2;
UIUtil.drawLine(g, x, clip.y, x, clip.y + clip.height);
UIUtil.drawVDottedLine((Graphics2D)g, x, clip.y, clip.y + clip.height, null, getOutlineColor(false));
paintLineNumbers(g);
}
}
public Color getBackground() {
if (myBackgroundColor == null) {
final Color userDefinedColor = myEditor.getColorsScheme().getColor(EditorColors.LEFT_GUTTER_BACKGROUND);
if (userDefinedColor != null) {
myBackgroundColor = userDefinedColor;
}
else {
LafManager lafManager = LafManager.getInstance();
if (lafManager != null && lafManager.isUnderAquaLookAndFeel()) {
myBackgroundColor = new Color(0xF0F0F0);
}
else {
myBackgroundColor = super.getBackground();
}
}
Color color = myEditor.getColorsScheme().getColor(EditorColors.GUTTER_BACKGROUND);
myBackgroundColor = color == null ? new Color(0xF0F0F0) : color;
}
return myBackgroundColor;
}
@@ -639,8 +631,8 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
return (myEditor.getLineHeight() - icon.getIconHeight()) /2;
}
public Color getFoldingColor(boolean isActive) {
ColorKey key = isActive ? EditorColors.SELECTED_FOLDING_TREE_COLOR : EditorColors.FOLDING_TREE_COLOR;
public Color getOutlineColor(boolean isActive) {
ColorKey key = isActive ? EditorColors.SELECTED_TEARLINE_COLOR : EditorColors.TEARLINE_COLOR;
Color color = myEditor.getColorsScheme().getColor(key);
return color != null ? color : Color.black;
}
@@ -706,7 +698,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
if (!isFoldingOutlineShown()) return;
Rectangle clip = g.getClipBounds();
UIUtil.drawVDottedLine(g, getWhitespaceSeparatorOffset(), clip.y, clip.y + clip.height, myEditor.getBackgroundColor(), getFoldingColor(false));
UIUtil.drawVDottedLine(g, getWhitespaceSeparatorOffset(), clip.y, clip.y + clip.height, null, getOutlineColor(false));
int anchorX = getFoldingAreaOffset();
int width = getFoldingAnchorWidth();
@@ -820,7 +812,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
g.fillPolygon(xPoints, yPoints, 5);
}
else {
g.setColor(getFoldingColor(active));
g.setColor(getOutlineColor(active));
g.drawPolygon(xPoints, yPoints, 5);
//Minus
@@ -855,11 +847,11 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
g.fillRect(anchorX, y, width, width);
}
else {
g.setColor(getFoldingColor(active));
g.setColor(getOutlineColor(active));
g.drawRect(anchorX, y, width, width);
// Draw plus
if (!active) g.setColor(getFoldingColor(true));
if (!active) g.setColor(getOutlineColor(true));
UIUtil.drawLine(g, anchorX + 2, y + width / 2, anchorX + width - 2, y + width / 2);
}
}
@@ -876,7 +868,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
int lineX = anchorX + width / 2;
g.setColor(getFoldingColor(true));
g.setColor(getOutlineColor(true));
UIUtil.drawLine(g, lineX, startY, lineX, endY);
}
}
@@ -176,7 +176,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
private static final int MOUSE_SELECTION_STATE_LINE_SELECTED = 2;
private final MarkupModelListener myMarkupModelListener;
private final List<TextChange> mySoftWrapsOnLastRepaint = new ArrayList<TextChange>();
private EditorHighlighter myHighlighter;
private final TextDrawingCallback myTextDrawingCallback = new MyTextDrawingCallback();
@@ -216,6 +215,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
private boolean myEmbeddedIntoDialogWrapper;
private CachedFontContent myLastCache;
private boolean mySpacesHaveSameWidth;
private boolean mySoftWrapsChanged;
private Point myLastBackgroundPosition = null;
private Color myLastBackgroundColor = null;
@@ -327,6 +327,14 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
myFoldingModel.flushCaretShift();
myScrollBarOrientation = VERTICAL_SCROLLBAR_RIGHT;
mySoftWrapModel.addSoftWrapChangeListener(new SoftWrapChangeListener() {
@Override
public void softWrapsStateChanged(int changedLogicalLine) {
mySoftWrapsChanged = true;
mySizeContainer.update(changedLogicalLine, changedLogicalLine, changedLogicalLine);
}
});
EditorHighlighter highlighter = new EmptyEditorHighlighter(myScheme.getAttributes(HighlighterColors.TEXT));
setHighlighter(highlighter);
@@ -1692,8 +1700,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
// Perform additional activity if soft wrap is added or removed during repainting.
// Note: this code lives in this method in assumption that background repainting is the very first activity performed
// during whole editor component repaint.
List<? extends TextChange> softWrapsAfterRepaint = mySoftWrapModel.getRegisteredSoftWraps();
if (!mySoftWrapsOnLastRepaint.equals(softWrapsAfterRepaint)) {
if (mySoftWrapsChanged) {
mySoftWrapsChanged = false;
validateSize();
// Repaint editor to the bottom in order to ensure that its content is shown correctly after new soft wrap introduction.
repaintToScreenBottom(xyToLogicalPosition(position).line);
@@ -1704,8 +1714,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
// Ask caret model to update visual caret position.
getCaretModel().moveToOffset(getCaretModel().getOffset());
}
mySoftWrapsOnLastRepaint.clear();
mySoftWrapsOnLastRepaint.addAll(softWrapsAfterRepaint);
}
private void paintRectangularSelection(Graphics g) {
@@ -2482,11 +2490,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
public Dimension getContentSize() {
Dimension size = mySizeContainer.getContentSize();
//TODO den move soft wrap-related logic to editor size container
return new Dimension(
size.width,
size.height + (mySettings.getAdditionalLinesCount() + mySoftWrapModel.getSoftWrapsIntroducedLinesNumber()) * getLineHeight()
);
return new Dimension(size.width, size.height + mySettings.getAdditionalLinesCount() * getLineHeight());
}
public JScrollPane getScrollPane() {
@@ -2524,10 +2528,20 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
return myLastColumnNumber;
}
/**
* @return information about total number of lines that can be viewed by user. I.e. this is a number of all document
* lines (considering that single logical document line may be represented on multiple visual lines because of
* soft wraps appliance) minus number of folded lines
*/
int getVisibleLineCount() {
int line = getDocument().getLineCount() + getSoftWrapModel().getSoftWrapsIntroducedLinesNumber();
line -= myFoldingModel.getFoldedLinesCountBefore(getDocument().getTextLength() + 1);
return line;
return getVisibleLogicalLinesCount() + getSoftWrapModel().getSoftWrapsIntroducedLinesNumber();
}
/**
* @return number of visible logical lines. Generally, that is a total logical lines number minus number of folded lines
*/
private int getVisibleLogicalLinesCount() {
return getDocument().getLineCount() - myFoldingModel.getFoldedLinesCountBefore(getDocument().getTextLength() + 1);
}
@NotNull
@@ -4595,15 +4609,25 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
}
@SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"})
private class EditorSizeContainer {
/** Holds logical line widths in pixels. */
private TIntArrayList myLineWidths;
/** Holds value that indicates if line widths recalculation should be performed. */
private volatile boolean myIsDirty;
/** Holds number of the last logical line affected by the last document change. */
private int myOldEndLine;
private Dimension mySize;
private int myMaxWidth = -1;
private final Object lock = new Object();
private int myMaxWidth = -1;
public synchronized void reset() {
int visLinesCount = getVisibleLineCount();
int visLinesCount = getDocument().getLineCount();
myLineWidths = new TIntArrayList(visLinesCount + 300);
int[] values = new int[visLinesCount];
Arrays.fill(values, -1);
@@ -4611,6 +4635,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
myIsDirty = true;
}
@SuppressWarnings({"NonPrivateFieldAccessedInSynchronizedContext"})
public synchronized void beforeChange(DocumentEvent e) {
if (myDocument.isInBulkUpdate()) {
myMaxWidth = mySize != null ? mySize.width : -1;
@@ -4626,11 +4651,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
return offsetToVisualPosition(startLineOffset).line;
}
public synchronized void changedUpdate(DocumentEvent e) {
int startLine = e.getOldLength() == 0 ? myOldEndLine : getVisualPositionLine(e.getOffset());
int newEndLine = e.getNewLength() == 0 ? startLine : getVisualPositionLine(e.getOffset() + e.getNewLength());
int oldEndLine = myOldEndLine;
public synchronized void update(int startLine, int newEndLine, int oldEndLine) {
final int lineWidthSize = myLineWidths.size();
if (lineWidthSize == 0) {
reset();
@@ -4657,12 +4678,21 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
}
public synchronized void changedUpdate(DocumentEvent e) {
int startLine = e.getOldLength() == 0 ? myOldEndLine : getVisualPositionLine(e.getOffset());
int newEndLine = e.getNewLength() == 0 ? startLine : getVisualPositionLine(e.getOffset() + e.getNewLength());
int oldEndLine = myOldEndLine;
update(startLine, newEndLine, oldEndLine);
}
@SuppressWarnings({"NonPrivateFieldAccessedInSynchronizedContext", "AssignmentToForLoopParameter"})
private void validateSizes() {
if (!myIsDirty) return;
synchronized (this) {
synchronized (lock) {
if (!myIsDirty) return;
int lineCount = myLineWidths.size();
int lineCount = Math.min(myLineWidths.size(), myDocument.getLineCount());
if (myMaxWidth != -1 && myDocument.isInBulkUpdate()) {
mySize = new Dimension(myMaxWidth, getLineHeight() * lineCount);
@@ -4676,19 +4706,31 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
final int fontSize = myScheme.getEditorFontSize();
final String fontName = myScheme.getEditorFontName();
List<? extends TextChange> softWraps = getSoftWrapModel().getRegisteredSoftWraps();
int softWrapsIndex = -1;
for (int line = 0; line < lineCount; line++) {
if (myLineWidths.getQuick(line) != -1) continue;
x = 0;
int offset = logicalPositionToOffset(visualToLogicalPosition(new VisualPosition(line, 0)));
int offset = myDocument.getLineStartOffset(line);
if (offset >= myDocument.getTextLength()) {
myLineWidths.set(line, 0);
break;
}
if (softWrapsIndex < 0) {
softWrapsIndex = getSoftWrapModel().getSoftWrapIndex(offset);
if (softWrapsIndex < 0) {
softWrapsIndex = -softWrapsIndex - 1;
}
}
IterationState state = new IterationState(EditorImpl.this, offset, false);
int fontType = state.getMergedAttributes().getFontType();
int maxPreviousSoftWrappedWidth = -1;
while (offset < end && line < lineCount) {
char c = text.charAt(offset);
if (offset >= state.getEndOffset()) {
@@ -4696,6 +4738,22 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
fontType = state.getMergedAttributes().getFontType();
}
while (softWrapsIndex < softWraps.size()) {
TextChange softWrap = softWraps.get(softWrapsIndex);
if (softWrap.getStart() > offset) {
break;
}
softWrapsIndex++;
if (softWrap.getStart() == offset) {
maxPreviousSoftWrappedWidth = Math.max(maxPreviousSoftWrappedWidth, x);
x = getSoftWrapModel().getSoftWrapIndentWidthInPixels(softWrap);
}
}
if (line + 1 >= lineCount) {
myLineWidths.set(line, Math.max(x, maxPreviousSoftWrappedWidth));
break;
}
FoldRegion collapsed = state.getCurrentFold();
if (collapsed != null) {
String placeholder = collapsed.getPlaceholderText();
@@ -4703,6 +4761,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
x += EditorUtil.charWidth(placeholder.charAt(i), fontType, EditorImpl.this);
}
offset = collapsed.getEndOffset();
line = myDocument.getLineNumber(offset);
}
else {
if (c == '\t') {
@@ -4711,7 +4770,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
else {
if (c == '\n') {
myLineWidths.set(line, x);
myLineWidths.set(line, Math.max(x, maxPreviousSoftWrappedWidth));
if (line + 1 >= lineCount || myLineWidths.getQuick(line + 1) != -1) break;
offset++;
x = 0;
@@ -4732,12 +4791,28 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
x); // Last line can be non-zero length and won't be caught by in-loop procedure since latter only react on \n's
}
// There is a following possible situation:
// 1. Big document is opened at editor;
// 2. Soft wraps are calculated for the current visible area;
// 2. The user scrolled down;
// 3. The user significantly reduced visible area width (say, reduced it twice);
// 4. Soft wraps are calculated for the current visible area;
// We need to consider only the widths for the logical lines that are completely shown at the current visible area then.
// I.e. we shouldn't use widths of the lines that are not shown for max width calculation because previous widths are calculated
// for another visible area width.
int startToUse = 0;
int endToUse = lineCount;
if (getSoftWrapModel().isSoftWrappingEnabled()) {
Rectangle visibleArea = getScrollingModel().getVisibleArea();
startToUse = xyToLogicalPosition(visibleArea.getLocation()).line + 1;
endToUse = xyToLogicalPosition(new Point(0, visibleArea.y + visibleArea.height)).line;
}
int maxWidth = 0;
for (int i = 0; i < lineCount; i++) {
for (int i = startToUse; i < endToUse; i++) {
maxWidth = Math.max(maxWidth, myLineWidths.getQuick(i));
}
mySize = new Dimension(maxWidth, getLineHeight() * lineCount);
mySize = new Dimension(maxWidth, getLineHeight() * getVisibleLineCount());
myIsDirty = false;
}
@@ -15,11 +15,9 @@
*/
package com.intellij.openapi.editor.impl;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.editor.TextChange;
import com.intellij.openapi.editor.VisualPosition;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.ex.SoftWrapChangeListener;
import com.intellij.openapi.editor.ex.SoftWrapModelEx;
import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.openapi.editor.impl.softwrap.*;
@@ -56,7 +54,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx {
private int myActive;
public SoftWrapModelImpl(@NotNull EditorEx editor) {
this(editor, new SoftWrapsStorage(), new CompositeSoftWrapPainter(editor));
this(editor, new SoftWrapsStorage(editor.getDocument()), new CompositeSoftWrapPainter(editor));
}
public SoftWrapModelImpl(@NotNull final EditorEx editor, @NotNull SoftWrapsStorage storage, @NotNull SoftWrapPainter painter) {
@@ -77,7 +75,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx {
}
public boolean isSoftWrappingEnabled() {
return myEditor.getSettings().isUseSoftWraps();
return myEditor.getSettings().isUseSoftWraps() && !myEditor.isOneLineMode();
}
@Nullable
@@ -88,6 +86,11 @@ public class SoftWrapModelImpl implements SoftWrapModelEx {
return myStorage.getSoftWrap(offset);
}
@Override
public int getSoftWrapIndex(int offset) {
return myStorage.getSoftWrapIndex(offset);
}
@NotNull
@Override
public List<? extends TextChange> getSoftWrapsForRange(int start, int end) {
@@ -138,8 +141,11 @@ public class SoftWrapModelImpl implements SoftWrapModelEx {
return 0;
}
int result = 0;
for (TextChange myWrap : myStorage.getSoftWraps()) {
result += StringUtil.countNewLines(myWrap.getText());
FoldingModel foldingModel = myEditor.getFoldingModel();
for (TextChange softWrap : myStorage.getSoftWraps()) {
if (!foldingModel.isOffsetCollapsed(softWrap.getStart())) {
result += StringUtil.countNewLines(softWrap.getText());
}
}
return result;
}
@@ -309,4 +315,9 @@ public class SoftWrapModelImpl implements SoftWrapModelEx {
// Restore caret position.
myEditor.getCaretModel().moveToVisualPosition(visualCaretPosition);
}
@Override
public boolean addSoftWrapChangeListener(@NotNull SoftWrapChangeListener listener) {
return myStorage.addSoftWrapChangeListener(listener);
}
}
@@ -15,12 +15,16 @@
*/
package com.intellij.openapi.editor.impl.softwrap;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.ex.SoftWrapChangeListener;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* Holds registered soft wraps and provides monitoring and management facilities for them.
@@ -32,8 +36,15 @@ import java.util.List;
*/
public class SoftWrapsStorage {
private final List<TextChangeImpl> myWraps = new ArrayList<TextChangeImpl>();
private final List<TextChangeImpl> myWrapsView = Collections.unmodifiableList(myWraps);
private final List<TextChangeImpl> myWraps = new ArrayList<TextChangeImpl>();
private final List<TextChangeImpl> myWrapsView = Collections.unmodifiableList(myWraps);
private final Set<SoftWrapChangeListener> myListeners = new CopyOnWriteArraySet<SoftWrapChangeListener>();
private final Document myDocument;
public SoftWrapsStorage(Document document) {
myDocument = document;
}
/**
* @return <code>true</code> if there is at least one soft wrap registered at the current storage; <code>false</code> otherwise
@@ -103,6 +114,10 @@ public class SoftWrapsStorage {
i = -i - 1;
myWraps.add(i, softWrap);
int changedLogicalLine = myDocument.getLineNumber(softWrap.getStart());
for (SoftWrapChangeListener listener : myListeners) {
listener.softWrapsStateChanged(changedLogicalLine);
}
return null;
}
@@ -127,4 +142,14 @@ public class SoftWrapsStorage {
public void removeAll() {
myWraps.clear();
}
/**
* Registers given listener within the current model
*
* @param listener listener to register
* @return <code>true</code> if given listener was not registered before; <code>false</code> otherwise
*/
public boolean addSoftWrapChangeListener(@NotNull SoftWrapChangeListener listener) {
return myListeners.add(listener);
}
}
@@ -20,6 +20,8 @@ import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.fileEditor.*;
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.project.DumbService;
@@ -29,6 +31,7 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.FocusWatcher;
import com.intellij.ui.PrevNextActionsDescriptor;
import com.intellij.ui.SideBorder;
import com.intellij.ui.TabbedPaneWrapper;
import com.intellij.ui.tabs.UiDecorator;
import org.jetbrains.annotations.NotNull;
@@ -77,7 +80,6 @@ public abstract class EditorComposite implements Disposable {
private FileEditor mySelectedEditor;
private final FileEditorManagerEx myFileEditorManager;
private final long myInitialFileModificationStamp;
private final Map<FileEditor, FileEditorInfoPane> myInfoPanes = new HashMap<FileEditor, FileEditorInfoPane>();
private final Map<FileEditor, JComponent> myTopComponents = new HashMap<FileEditor, JComponent>();
private final Map<FileEditor, JComponent> myBottomComponents = new HashMap<FileEditor, JComponent>();
@@ -198,20 +200,14 @@ public abstract class EditorComposite implements Disposable {
component.add(comp, BorderLayout.CENTER);
final JPanel topPanel = new JPanel();
topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.Y_AXIS));
JPanel topPanel = new TopBottomPanel();
myTopComponents.put(editor, topPanel);
component.add(topPanel, BorderLayout.NORTH);
final JPanel bottomPanel = new JPanel();
bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.Y_AXIS));
final JPanel bottomPanel = new TopBottomPanel();
myBottomComponents.put(editor, bottomPanel);
component.add(bottomPanel, BorderLayout.SOUTH);
FileEditorInfoPane infoPane = new FileEditorInfoPane();
myInfoPanes.put(editor, infoPane);
addTopComponent(editor, infoPane);
return component;
}
@@ -307,17 +303,13 @@ public abstract class EditorComposite implements Disposable {
assert container != null;
if (remove) {
container.remove(component);
container.remove(component.getParent());
} else {
container.add(component);
container.add(new TopBottomComponentWrapper(component, top));
}
container.revalidate();
}
public FileEditorInfoPane getPane(FileEditor editor) {
return myInfoPanes.get(editor);
}
/**
* @return currently selected myEditor. The method never returns <code>null</code>.
*/
@@ -409,4 +401,33 @@ public abstract class EditorComposite implements Disposable {
public void dispose() {
}
private class TopBottomPanel extends JPanel {
private TopBottomPanel() {
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
}
@Override
public Color getBackground() {
Color color = EditorColorsManager.getInstance().getGlobalScheme().getColor(EditorColors.GUTTER_BACKGROUND);
return color == null ? Color.gray : color;
}
}
private class TopBottomComponentWrapper extends JPanel {
public TopBottomComponentWrapper(JComponent component, boolean top) {
super(new BorderLayout());
setOpaque(false);
setBorder(new SideBorder(null, top ? SideBorder.BOTTOM : SideBorder.TOP, true) {
@Override
public Color getLineColor() {
Color result = EditorColorsManager.getInstance().getGlobalScheme().getColor(EditorColors.TEARLINE_COLOR);
return result == null ? Color.black : result;
}
});
add(component);
}
}
}
@@ -1,107 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.fileEditor.impl;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
/**
* @author max
*/
public class FileEditorInfoPane extends JPanel {
private int myCounter = 0;
private final JPanel myCards;
private final JButton myPrevButton;
private final JButton myNextButton;
private final java.util.List<JComponent> myComponents;
private final JPanel myButtonsPanel;
public FileEditorInfoPane() {
super(new BorderLayout());
final CardLayout layout = new CardLayout();
myCards = new JPanel(layout);
myComponents = new ArrayList<JComponent>();
add(myCards, BorderLayout.CENTER);
myPrevButton = new JButton("<");
myNextButton = new JButton(">");
myButtonsPanel = new JPanel(new GridLayout(1, 2));
myButtonsPanel.add(myPrevButton);
myButtonsPanel.add(myNextButton);
myPrevButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
layout.previous(myCards);
updateButtons();
}
});
myNextButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
layout.next(myCards);
updateButtons();
}
});
add(myButtonsPanel, BorderLayout.EAST);
myButtonsPanel.setVisible(false);
setVisible(false);
}
public void addInfo(JComponent component) {
myComponents.add(component);
myCards.add(component, String.valueOf(myCounter++));
updateButtons();
validate();
}
public void removeInfo(JComponent component) {
myComponents.remove(component);
myCards.remove(component);
updateButtons();
validate();
}
private int getCurrentCard() {
for (int i = 0; i < myComponents.size(); i++) {
if (myComponents.get(i).isVisible()) return i;
}
return -1;
}
private void updateButtons() {
int count = myComponents.size();
if (count > 0) {
setVisible(true);
if (count == 1) {
myButtonsPanel.setVisible(false);
}
else {
myButtonsPanel.setVisible(true);
int currentCard = getCurrentCard();
myNextButton.setEnabled(currentCard + 1 < count);
myPrevButton.setEnabled(currentCard - 1 >= 0);
}
}
else {
setVisible(false);
}
}
}
@@ -915,17 +915,11 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
}
public void showEditorAnnotation(@NotNull FileEditor editor, @NotNull JComponent annotationComponent) {
final EditorComposite composite = getEditorComposite(editor);
if (composite != null) {
composite.getPane(editor).addInfo(annotationComponent);
}
addTopComponent(editor, annotationComponent);
}
public void removeEditorAnnotation(@NotNull FileEditor editor, @NotNull JComponent annotationComponent) {
final EditorComposite composite = getEditorComposite(editor);
if (composite != null) {
composite.getPane(editor).removeInfo(annotationComponent);
}
removeTopComponent(editor, annotationComponent);
}
public void addTopComponent(@NotNull final FileEditor editor, @NotNull final JComponent component) {
@@ -1,5 +1,6 @@
package com.intellij.openapi.editor.impl.softwrap;
import com.intellij.idea.Bombed;
import com.intellij.mock.MockFoldRegion;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.ex.EditorEx;
@@ -17,10 +18,7 @@ import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.*;
/**
* @author Denis Zhdanov
@@ -85,9 +83,10 @@ public class SoftWrapDataMapperTest {
myMockery = new JUnit4Mockery() {{
setImposteriser(ClassImposteriser.INSTANCE);
}};
myStorage = new SoftWrapsStorage();
myEditor = myMockery.mock(EditorEx.class);
myDocument = myMockery.mock(Document.class);
myStorage = new SoftWrapsStorage(myDocument);
myFoldingModel = myMockery.mock(FoldingModel.class);
final EditorSettings settings = myMockery.mock(EditorSettings.class);
final Project project = myMockery.mock(Project.class);
@@ -177,6 +176,7 @@ public class SoftWrapDataMapperTest {
myMockery.assertIsSatisfied();
}
@Bombed(day = 12, month = Calendar.JULY)
@Test
public void softWrapHasSymbolBeforeFirstLineFeed() {
String document =
@@ -192,6 +192,7 @@ public class SoftWrapDataMapperTest {
test(document);
}
@Bombed(day = 12, month = Calendar.JULY)
@Test
public void multipleSoftWrappedLogicalLines() {
String document =
@@ -211,6 +212,7 @@ public class SoftWrapDataMapperTest {
test(document);
}
@Bombed(day = 12, month = Calendar.JULY)
@Test
public void softWrapAndFoldedLines() {
String document =
@@ -107,8 +107,9 @@ options.xml.attribute.descriptor.descriptor.entity,reference=Entity reference
options.general.color.descriptor.background.in.readonly.files=Background in readonly files
options.deneral.color.descriptor.readonly.fragment.background=Readonly fragment background
options.general.color.descriptor.gutter.background=Gutter background
options.general.color.descriptor.selection.background=Selection Background
options.general.color.descriptor.selection.foreground=Selection Foreground
options.general.color.descriptor.notification.background=Notification background
options.general.color.descriptor.selection.background=Selection background
options.general.color.descriptor.selection.foreground=Selection foreground
options.general.color.descriptor.caret=Caret
options.general.color.descriptor.caret.row=Caret row
options.general.color.descriptor.right.margin=Right margin
@@ -118,8 +119,8 @@ options.general.color.descriptor.indent.guide.selected=Selected vertical indent
options.general.color.descriptor.line.number=Line number
options.general.color.descriptor.vcs.annotations=VCS annotations
options.general.color.descriptor.vcs.annotations.merged=VCS annotations (merged from)
options.general.color.descriptor.folding.outline=Folding outline
options.general.color.descriptor.selected.folding.outline=Selected folding outline
options.general.color.descriptor.tearline=Tear line
options.general.color.descriptor.tearline.selected=Selected tear line
options.general.color.descriptor.added.lines=Added lines
options.general.color.descriptor.modified.lines=Modified lines
options.general.color.descriptor.console.background=Console background
@@ -11,6 +11,8 @@
<option name="METHOD_SEPARATORS_COLOR" value="c0c0c0"/>
<option name="WHITESPACES" value="c5c5c5"/>
<option name="INDENT_GUIDE" value="e6e6e6"/>
<option name="GUTTER_BACKGROUND" value="f0f0f0" />
<option name="NOTIFICATION_BACKGROUND" value="ffffcc" />
<option name="SELECTED_INDENT_GUIDE" value="c8c8c8"/>
<option name="SELECTION_FOREGROUND" value="ffffff"/>
<option name="LINE_NUMBERS_COLOR" value="800000"/>
@@ -18,8 +20,8 @@
<option name="ANNOTATIONS_MERGED_COLOR" value="008080" />
<option name="CARET_COLOR" value="0"/>
<option name="RIGHT_MARGIN_COLOR" value="c0c0c0"/>
<option name="FOLDING_TREE_COLOR" value="808080"/>
<option name="SELECTED_FOLDING_TREE_COLOR" value="000000"/>
<option name="TEARLINE_COLOR" value="808080"/>
<option name="SELECTED_TEARLINE_COLOR" value="000000"/>
<option name="READONLY_FRAGMENT_BACKGROUND" value="cfe7ff"/>
<option name="ADDED_LINES_COLOR" value="edfced"/>
@@ -41,6 +41,7 @@
interface="com.intellij.javaee.ImplicitNamespaceDescriptorProvider"/>
<extensionPoint name="xml.zenCodingGenerator" interface="com.intellij.codeInsight.template.zencoding.filters.ZenCodingGenerator"/>
<extensionPoint name="xml.zenCodingFilter" interface="com.intellij.codeInsight.template.zencoding.filters.ZenCodingFilter"/>
</extensionPoints>
<extensions defaultExtensionNs="com.intellij">
@@ -17,8 +17,13 @@ package com.intellij.openapi.util;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@SuppressWarnings({"AssignmentToStaticFieldFromInstanceMethod", "UnusedDeclaration"})
/**
* @author max
* @author Konstantin Bulenkov
*/
@SuppressWarnings({"AssignmentToStaticFieldFromInstanceMethod", "UnusedDeclaration", "EqualsWhichDoesntCheckParameterClass"})
public class Key<T> {
private static int ourKeysCounter = 0;
private final int myIndex = ourKeysCounter++;
@@ -45,4 +50,32 @@ public class Key<T> {
public static <T> Key<T> create(@NotNull @NonNls String name) {
return new Key<T>(name);
}
}
@Nullable
public T get(@Nullable UserDataHolder holder) {
return holder == null ? null : holder.getUserData(this);
}
public T get(@Nullable UserDataHolder holder, T defaultValue) {
final T t = get(holder);
return t == null ? defaultValue : t;
}
/**
* Returns <code>true</code> if and only if the <code>holder</code> has
* not null value by the key.
*
* @param holder user data holder object
* @return <code>true</code> if holder.getUserData(this) != null
* <code>false</code> otherwise.
*/
public boolean isIn(@Nullable UserDataHolder holder) {
return get(holder) != null;
}
public void set(@Nullable UserDataHolder holder, T value) {
if (holder != null) {
holder.putUserData(this, value);
}
}
}
@@ -66,24 +66,24 @@ public class SideBorder extends LineBorder {
g.setColor(getLineColor());
for(i = 0; i < getThickness(); i++){
if ((mySideMask & LEFT) != 0){
drawLine(g, x + i, y + i, x + i, height - i - i - 1);
drawLine(c, g, x + i, y + i, x + i, height - i - i - 1);
}
if ((mySideMask & TOP) != 0){
drawLine(g, x + i, y + i, width - i - i - 1, y + i);
drawLine(c, g, x + i, y + i, width - i - i - 1, y + i);
}
if ((mySideMask & RIGHT) != 0){
drawLine(g, width - i - i - 1, y + i, width - i - i - 1, height - i - i - 1);
drawLine(c, g, width - i - i - 1, y + i, width - i - i - 1, height - i - i - 1);
}
if ((mySideMask & BOTTOM) != 0){
drawLine(g, x + i, height - i - i - 1, width - i - i - 1, height - i - i - 1);
drawLine(c, g, x + i, height - i - i - 1, width - i - i - 1, height - i - i - 1);
}
}
g.setColor(oldColor);
}
private void drawLine(Graphics g, int x1, int y1, int x2, int y2) {
private void drawLine(Component c, Graphics g, int x1, int y1, int x2, int y2) {
if (myDotted) {
UIUtil.drawDottedLine((Graphics2D)g, x1, y1, x2, y2, ((Graphics2D)g).getBackground(), getLineColor());
UIUtil.drawDottedLine((Graphics2D)g, x1, y1, x2, y2, null, getLineColor());
}
else {
UIUtil.drawLine(g, x1, y1, x2, y2);
@@ -889,20 +889,23 @@ public class UIUtil {
});
}
public static void drawVDottedLine(Graphics2D g, int lineX, int startY, int endY, final Color bgColor, final Color fgColor) {
g.setColor(bgColor);
drawLine(g, lineX, startY, lineX, endY);
public static void drawVDottedLine(Graphics2D g, int lineX, int startY, int endY, @Nullable final Color bgColor, final Color fgColor) {
if (bgColor != null) {
g.setColor(bgColor);
drawLine(g, lineX, startY, lineX, endY);
}
g.setColor(fgColor);
for (int i = (startY / 2) * 2; i < endY; i += 2) {
g.drawRect(lineX, i, 0, 0);
}
}
public static void drawHDottedLine(Graphics2D g, int startX, int endX, int lineY, final Color bgColor, final Color fgColor) {
g.setColor(bgColor);
drawLine(g, startX, lineY, endX, lineY);
public static void drawHDottedLine(Graphics2D g, int startX, int endX, int lineY, @Nullable final Color bgColor, final Color fgColor) {
if (bgColor != null) {
g.setColor(bgColor);
drawLine(g, startX, lineY, endX, lineY);
}
g.setColor(fgColor);
@@ -911,7 +914,7 @@ public class UIUtil {
}
}
public static void drawDottedLine(Graphics2D g, int x1, int y1, int x2, int y2, final Color bgColor, final Color fgColor) {
public static void drawDottedLine(Graphics2D g, int x1, int y1, int x2, int y2, @Nullable final Color bgColor, final Color fgColor) {
if (x1 == x2) {
drawVDottedLine(g, x1, y1, y2, bgColor, fgColor);
}
@@ -15,8 +15,23 @@
*/
package com.intellij.openapi.vcs.annotate;
public abstract class LineAnnotationAspectAdapter implements LineAnnotationAspect {
import com.intellij.openapi.editor.EditorGutterAction;
import java.awt.*;
public abstract class LineAnnotationAspectAdapter implements LineAnnotationAspect, EditorGutterAction {
public String getTooltipText(int lineNumber) {
return null;
}
public Cursor getCursor(final int lineNum) {
return Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
}
@Override
public void doAction(int lineNum) {
showAffectedPaths(lineNum);
}
protected abstract void showAffectedPaths(int lineNum);
}
@@ -18,6 +18,7 @@ package com.intellij.openapi.vcs.changes.committed;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
@@ -216,7 +216,7 @@ public class LineStatusTracker {
int width = endX - x;
if (r.height > 0) {
g.fillRect(x, r.y + 2, width, r.height - 4);
g.setColor(gutter.getFoldingColor(false));
g.setColor(gutter.getOutlineColor(false));
UIUtil.drawLine(g, x, r.y + 2, x + width, r.y + 2);
UIUtil.drawLine(g, x, r.y + 2, x, r.y + r.height - 3);
UIUtil.drawLine(g, x, r.y + r.height - 3, x + width, r.y + r.height - 3);
@@ -230,7 +230,7 @@ public class LineStatusTracker {
r.y};
g.fillPolygon(xPoints, yPoints, 3);
g.setColor(gutter.getFoldingColor(false));
g.setColor(gutter.getOutlineColor(false));
g.drawPolygon(xPoints, yPoints, 3);
}
}
@@ -37,7 +37,7 @@ public class CvsFileAnnotation implements FileAnnotation{
private final VirtualFile myFile;
private final List<AnnotationListener> myListeners = new ArrayList<AnnotationListener>();
private final LineAnnotationAspect USER = new LineAnnotationAspectAdapter() {
private final LineAnnotationAspect USER = new CvsAnnotationAspect() {
public String getValue(int lineNumber) {
if (lineNumber < 0 || lineNumber >= myAnnotations.length) {
return "";
@@ -48,7 +48,7 @@ public class CvsFileAnnotation implements FileAnnotation{
}
};
private final LineAnnotationAspect DATE = new LineAnnotationAspectAdapter() {
private final LineAnnotationAspect DATE = new CvsAnnotationAspect() {
public String getValue(int lineNumber) {
if (lineNumber < 0 || lineNumber >= myAnnotations.length) {
return "";
@@ -59,7 +59,7 @@ public class CvsFileAnnotation implements FileAnnotation{
}
};
private final LineAnnotationAspect REVISION = new LineAnnotationAspectAdapter() {
private final LineAnnotationAspect REVISION = new CvsAnnotationAspect() {
public String getValue(int lineNumber) {
if (lineNumber < 0 || lineNumber >= myAnnotations.length) {
return "";
@@ -172,4 +172,10 @@ public class CvsFileAnnotation implements FileAnnotation{
return null;
}
private abstract class CvsAnnotationAspect extends LineAnnotationAspectAdapter {
@Override
protected void showAffectedPaths(int lineNum) {
//todo
}
}
}
@@ -20,13 +20,11 @@ import com.intellij.openapi.components.*;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleServiceManager;
import com.intellij.openapi.roots.impl.storage.ClasspathStorage;
import com.intellij.openapi.util.text.StringUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.*;
@State(
name = "EclipseModuleManager",
@@ -44,12 +42,13 @@ public class EclipseModuleManager implements PersistentStateComponent<Element>{
@NonNls private static final String CONELEMENT = "conelement";
@NonNls private static final String FORCED_JDK = "forced_jdk";
private CachedXmlDocumentSet myDocumentSet;
private final Map<String, String> myEclipseVariablePaths = new HashMap<String, String>();
private final Set<String> myEclipseUrls = new HashSet<String>();
private final Set<String> myUnknownCons = new HashSet<String>();
private final Map<String, String> myEclipseVariablePaths = new LinkedHashMap<String, String>();
private final Set<String> myEclipseUrls = new LinkedHashSet<String>();
private final Set<String> myUnknownCons = new LinkedHashSet<String>();
private boolean myForceConfigureJDK = false;
private static final String SRC_PREFIX = "src:";
private static final String SRC_LINK_PREFIX = "linksrc:";
@NonNls private static final String SRC_PREFIX = "src:";
@NonNls private static final String SRC_LINK_PREFIX = "linksrc:";
@NonNls private static final String PREFIX_ATTR = "kind";
private final Module myModule;
@NonNls private static final String LIBELEMENT = "libelement";
@@ -118,7 +117,7 @@ public class EclipseModuleManager implements PersistentStateComponent<Element>{
}
public Element getState() {
if (ClasspathStorage.getStorageType(myModule) != EclipseClasspathStorageProvider.ID) {
if (!ClasspathStorage.getStorageType(myModule).equals(EclipseClasspathStorageProvider.ID)) {
if (!myEclipseUrls.isEmpty() || !myEclipseVariablePaths.isEmpty() || myForceConfigureJDK || !myUnknownCons.isEmpty()) {
Element root = new Element("EclipseModuleSettings");
for (String eclipseUrl : myEclipseUrls) {
@@ -128,7 +127,15 @@ public class EclipseModuleManager implements PersistentStateComponent<Element>{
}
for (String var : myEclipseVariablePaths.keySet()) {
Element varElement = new Element(VARELEMENT);
varElement.setAttribute(VAR_ATTRIBUTE, var);
if (var.startsWith(SRC_PREFIX)) {
varElement.setAttribute(VAR_ATTRIBUTE, StringUtil.trimStart(var, SRC_PREFIX));
varElement.setAttribute(PREFIX_ATTR, SRC_PREFIX);
} else if (var.startsWith(SRC_LINK_PREFIX)) {
varElement.setAttribute(VAR_ATTRIBUTE, StringUtil.trimStart(var, SRC_LINK_PREFIX));
varElement.setAttribute(PREFIX_ATTR, SRC_LINK_PREFIX);
} else {
varElement.setAttribute(VAR_ATTRIBUTE, var);
}
varElement.setAttribute(VALUE_ATTR, myEclipseVariablePaths.get(var));
root.addContent(varElement);
}
@@ -153,7 +160,8 @@ public class EclipseModuleManager implements PersistentStateComponent<Element>{
}
for (Object o : state.getChildren(VARELEMENT)) {
myEclipseVariablePaths.put(((Element)o).getAttributeValue(VAR_ATTRIBUTE), ((Element)o).getAttributeValue(VALUE_ATTR));
final String prefix = ((Element)o).getAttributeValue(PREFIX_ATTR);
myEclipseVariablePaths.put(((Element)o).getAttributeValue(VAR_ATTRIBUTE), (prefix != null ? prefix : "") + ((Element)o).getAttributeValue(VALUE_ATTR));
}
for (Object o : state.getChildren(CONELEMENT)) {
@@ -16,7 +16,6 @@
package git4idea.annotate;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.EditorGutterAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.FileStatus;
import com.intellij.openapi.vcs.FileStatusListener;
@@ -89,14 +88,14 @@ public class GitFileAnnotation implements FileAnnotation {
*/
private final boolean myMonitorFlag;
private final LineAnnotationAspect DATE_ASPECT = new MyAnnotationAspect() {
private final LineAnnotationAspect DATE_ASPECT = new GitAnnotationAspect() {
public String doGetValue(LineInfo info) {
final Date date = info.getDate();
return date == null ? "" : DATE_FORMAT.format(date);
}
};
private final LineAnnotationAspect REVISION_ASPECT = new MyAnnotationAspect() {
private final LineAnnotationAspect REVISION_ASPECT = new GitAnnotationAspect() {
@Override
protected String doGetValue(LineInfo lineInfo) {
final GitRevisionNumber revision = lineInfo.getRevision();
@@ -104,7 +103,7 @@ public class GitFileAnnotation implements FileAnnotation {
}
};
private final LineAnnotationAspect AUTHOR_ASPECT = new MyAnnotationAspect() {
private final LineAnnotationAspect AUTHOR_ASPECT = new GitAnnotationAspect() {
@Override
protected String doGetValue(LineInfo lineInfo) {
final String author = lineInfo.getAuthor();
@@ -285,7 +284,7 @@ public class GitFileAnnotation implements FileAnnotation {
/**
* Revision annotation aspect implementation
*/
private abstract class MyAnnotationAspect extends LineAnnotationAspectAdapter implements EditorGutterAction {
private abstract class GitAnnotationAspect extends LineAnnotationAspectAdapter {
public String getValue(int lineNumber) {
if (myLines.size() <= lineNumber || lineNumber < 0 || myLines.get(lineNumber) == null) {
return "";
@@ -297,17 +296,8 @@ public class GitFileAnnotation implements FileAnnotation {
protected abstract String doGetValue(LineInfo lineInfo);
/**
* {@inheritDoc}
*/
public Cursor getCursor(final int lineNum) {
return Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
}
/**
* {@inheritDoc}
*/
public void doAction(int lineNum) {
@Override
protected void showAffectedPaths(int lineNum) {
if (lineNum >= 0 && lineNum < myLines.size()) {
final LineInfo info = myLines.get(lineNum);
VcsFileRevision revision = myRevisionMap.get(info.getRevision());
@@ -79,7 +79,7 @@ public class GroovyShortNamesCache extends PsiShortNamesCache {
@NotNull
public PsiClass[] getClassesByFQName(@NotNull @NonNls String name, @NotNull GlobalSearchScope scope) {
final Collection<PsiClass> result = getScriptClassesByFQName(name, scope);
final Collection<PsiClass> result = new ArrayList<PsiClass>(getScriptClassesByFQName(name, scope));
final Collection<? extends PsiElement> classes = StubIndex.getInstance().get(GrFullClassNameIndex.KEY, name.hashCode(), myProject, new GrSourceFilterScope(scope));
if (!classes.isEmpty()) {
@@ -14,10 +14,7 @@ package org.zmlx.hg4idea.provider.annotate;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.annotate.AnnotationListener;
import com.intellij.openapi.vcs.annotate.AnnotationSourceSwitcher;
import com.intellij.openapi.vcs.annotate.FileAnnotation;
import com.intellij.openapi.vcs.annotate.LineAnnotationAspect;
import com.intellij.openapi.vcs.annotate.*;
import com.intellij.openapi.vcs.changes.CurrentContentRevision;
import com.intellij.openapi.vcs.history.VcsFileRevision;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
@@ -108,7 +105,7 @@ public class HgAnnotation implements FileAnnotation {
return result;
}
class HgLineAnnotationAspect implements LineAnnotationAspect {
class HgLineAnnotationAspect extends LineAnnotationAspectAdapter {
private final FIELD aspectType;
public HgLineAnnotationAspect(FIELD aspectType) {
@@ -125,8 +122,9 @@ public class HgAnnotation implements FileAnnotation {
: annotationLine.get(aspectType).toString();
}
public String getTooltipText(int lineNumber) {
return null;
@Override
protected void showAffectedPaths(int lineNum) {
// todo
}
}
@@ -15,6 +15,7 @@
*/
package org.jetbrains.idea.maven.utils;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.FileEditorManagerAdapter;
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+31
View File
@@ -0,0 +1,31 @@
Copyright (c) 2002, 2003 Thai Open Source Software Center Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
Neither the name of the Thai Open Source Software Center Ltd nor
the names of its contributors may be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Binary file not shown.
+56
View File
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<module relativePaths="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="lang-api" />
<orderEntry type="module" module-name="xml" />
<orderEntry type="module" module-name="dom-openapi" />
<orderEntry type="module" module-name="lang-impl" />
<orderEntry type="module" module-name="testFramework" scope="TEST" />
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/rngom-20051226-patched.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$MODULE_DIR$/lib/rngom-src.zip!/src" />
</SOURCES>
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/isorelax.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/trang-core.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/jing.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>
+13
View File
@@ -0,0 +1,13 @@
Copyright 2007 Sascha Weinreuter
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.
@@ -0,0 +1,73 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Jing Copying Conditions</title>
</head>
<body>
<h1>Jing Copying Conditions</h1>
<p>Copyright (c) 2001-2003 Thai Open Source Software Center Ltd<br />
All rights reserved.</p>
<p>Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:</p>
<ul>
<li>Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.</li>
<li>Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.</li>
<li>Neither the name of the Thai Open Source Software Center Ltd nor
the names of its contributors may be used to endorse or promote
products derived from this software without specific prior written
permission.</li>
</ul>
<p>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</p>
<h2>Third-party JARs</h2>
<p>This distribution includes some additional JAR files, which have
their own copying conditions:</p>
<dl>
<dt><code>isorelax.jar</code></dt>
<dd>Comes from <a href="http://sourceforge.net/projects/iso-relax/">ISO RELAX</a>
2003/01/08 distribution and is covered by the following license:
<p>Copyright (c) 2001-2002, SourceForge ISO-RELAX Project (ASAMI Tomoharu, Daisuke
Okajima, Kohsuke Kawaguchi, and MURATA Makoto)</p>
<p>Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</p>
<p>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</p>
<p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p>
</dd>
</dl>
</body>
</html>
+93
View File
@@ -0,0 +1,93 @@
<idea-plugin version="2" url="http://www.jetbrains.net/confluence/display/CONTEST/RELAX-NG+Support">
<id>RelaxNG-Support</id>
<name>RELAX-NG Support</name>
<depends>com.intellij.modules.xml</depends>
<description><![CDATA[
Support for RELAX-NG XML schemas. See <a href="http://relaxng.org/">relaxng.org</a> and the corresponding
IntelliJ IDEA feature request: <a href="http://www.jetbrains.net/jira/browse/IDEA-13734">IDEA-13734</a>.
<p>
The plugin provides the following features:
</p>
<ul>
<li> Completion and validation of XML documents associated with RELAX-NG schemas</li>
<li> Editing RELAX-NG files in XML and compact syntax, including on-the-fly error checking, completion,
documentation lookup and more.</li>
<li> Conversion between different schema formats (including W3C XML Schema/XML 1.0 DTDs) using
<a href="http://www.thaiopensource.com/relaxng/trang.html">Trang</a></li>
</ul>
]]></description>
<version>1.5.5</version>
<change-notes><![CDATA[
<ul>
<li>extreme index optimization</li>
<li>renameable xml prefixes</li>
<li>IDEA 9.x compatibility bugfixes</li>
</ul>
<p>
The complete list of changes in earlier versions is available
<a href="http://www.jetbrains.net/confluence/display/CONTEST/RELAX-NG+Support#RELAX-NGSupport-VersionHistory">here</a>
</p>
]]></change-notes>
<vendor email="sascha.weinreuter@cit.de">Sascha Weinreuter</vendor>
<idea-version since-build="95.4" /><!-- 9.x -->
<extensions defaultExtensionNs="com.intellij">
<errorHandler implementation="org.intellij.plugins.relaxNG.SimpleErrorReportSubmitter" />
<gotoSymbolContributor implementation="org.intellij.plugins.relaxNG.GotoSymbolContributor" />
<xml.schemaProvider implementation="org.intellij.plugins.relaxNG.config.NoNamespaceSchemaProvider" />
<hectorComponentProvider implementation="org.intellij.plugins.relaxNG.config.NoNamespaceConfigImpl$HectorProvider" />
<fileTypeFactory implementation="org.intellij.plugins.relaxNG.compact.RncFileType$Factory" />
<completionData fileType="RNG Compact" className="org.intellij.plugins.relaxNG.compact.RncCompletionData" />
<standardResourceProvider implementation="org.intellij.plugins.relaxNG.ApplicationLoader$ResourceProvider" />
<annotator language="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.compact.ReferenceAnnotator" />
<annotator language="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.model.annotation.ModelAnnotator" />
<externalAnnotator language="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.validation.RngSchemaValidator" />
<lang.parserDefinition language="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.compact.RncParserDefinition" />
<lang.braceMatcher language="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.compact.RngCompactLanguage$MyPairedBraceMatcher" />
<lang.commenter language="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.compact.RngCompactLanguage$MyCommenter" />
<lang.foldingBuilder language="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.compact.folding.RncFoldingBuilder" />
<lang.formatter language="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.compact.formatting.RncFormattingModelBuilder" />
<lang.namesValidator language="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.compact.RngCompactLanguage$MyNamesValidator" />
<lang.syntaxHighlighterFactory key="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.compact.RngCompactLanguage$MySyntaxHighlighterFactory" />
<lang.elementManipulator forClass="org.intellij.plugins.relaxNG.compact.psi.RncFileReference" implementationClass="org.intellij.plugins.relaxNG.ProjectLoader$RncFileReferenceManipulator" />
<lang.documentationProvider language="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.compact.RngCompactLanguage$MyDocumentationProvider" />
<fileBasedIndex implementation="org.intellij.plugins.relaxNG.model.resolve.RelaxSymbolIndex" />
<include.provider implementation="org.intellij.plugins.relaxNG.model.resolve.RelaxIncludeProvider"/>
<externalAnnotator language="XML" implementationClass="org.intellij.plugins.relaxNG.validation.RngSchemaValidator" />
<lang.documentationProvider language="XML" implementationClass="org.intellij.plugins.relaxNG.RngDocumentationProvider" />
</extensions>
<project-components>
<component>
<implementation-class>org.intellij.plugins.relaxNG.ProjectLoader</implementation-class>
</component>
<component>
<interface-class>org.intellij.plugins.relaxNG.config.NoNamespaceConfig</interface-class>
<implementation-class>org.intellij.plugins.relaxNG.config.NoNamespaceConfigImpl</implementation-class>
</component>
</project-components>
<application-components>
<component>
<implementation-class>org.intellij.plugins.relaxNG.ApplicationLoader</implementation-class>
</component>
</application-components>
<actions>
<action id="ConvertSchemaAction" class="org.intellij.plugins.relaxNG.convert.ConvertSchemaAction"
text="Convert Schema..."
description="Converts the selected Schema document (RNG, RNC, XSD, DTD) into another format">
<add-to-group group-id="ToolsXmlGroup" anchor="after" relative-to-action="GenerateDTD" />
</action>
</actions>
</idea-plugin>
@@ -0,0 +1,25 @@
<html>
<head>
<style type="text/css">
body, table {
font-family: Verdana, sans-serif;
font-size: 100%;
padding-left: 2mm;
}
#footer {
font-size: 95%;
padding-top: 10px;
}
</style>
</head>
<body>
<p>
This inspections checks for any unresolved references to named patterns ("define") in a RELAX-NG file in XML Syntax.
For unresolved references, a QuickFix is offered to create a corresponding define-element.
</p>
<p id="footer">Powered by RELAX-NG Support</p>
</body>
</html>
@@ -0,0 +1,26 @@
<html>
<head>
<style type="text/css">
body, table {
font-family: Verdana, sans-serif;
font-size: 100%;
padding-left: 2mm;
}
#footer {
font-size: 95%;
padding-top: 10px;
}
</style>
</head>
<body>
<p>
This inspections checks for any unused named patterns ("define") in a RELAX-NG file (XML or Compact Syntax) and
highlights them as unused symbols. This is done with respect to includes from other files, i.e. a define is not
marked as unused if is is used through an include in another file.
</p>
<p id="footer">Powered by RELAX-NG Support</p>
</body>
</html>
@@ -0,0 +1,124 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG;
import org.intellij.plugins.relaxNG.compact.psi.impl.RncDocument;
import org.intellij.plugins.relaxNG.inspections.RngDomInspection;
import org.intellij.plugins.relaxNG.inspections.UnusedDefineInspection;
import org.intellij.plugins.relaxNG.model.descriptors.RngNsDescriptor;
import org.intellij.plugins.relaxNG.validation.ValidateAction;
import org.intellij.plugins.relaxNG.xml.dom.RngDefine;
import org.intellij.plugins.relaxNG.xml.dom.impl.RngDefineMetaData;
import com.intellij.codeInspection.InspectionToolProvider;
import com.intellij.javaee.ResourceRegistrar;
import com.intellij.javaee.StandardResourceProvider;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.psi.PsiElement;
import com.intellij.psi.filters.AndFilter;
import com.intellij.psi.filters.ClassFilter;
import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.filters.position.NamespaceFilter;
import com.intellij.psi.meta.MetaDataRegistrar;
import com.intellij.psi.xml.XmlDocument;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.xml.DomElement;
import com.intellij.util.xml.DomManager;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 18.07.2007
*/
public class ApplicationLoader implements ApplicationComponent, InspectionToolProvider {
private static final String RNG_EXT = "rng";
private static final String VALIDATE_XML = "ValidateXml";
@NonNls
@NotNull
public String getComponentName() {
return "Relax-NG";
}
public void initComponent() {
registerMetaData();
final FileTypeManager ftm = FileTypeManager.getInstance();
ftm.registerFileType(StdFileTypes.XML, RNG_EXT);
installValidateXmlAction();
}
private static void installValidateXmlAction() {
final ActionManager mgr = ActionManager.getInstance();
final AnAction validateAction = mgr.getAction(VALIDATE_XML);
mgr.unregisterAction(VALIDATE_XML);
mgr.registerAction(VALIDATE_XML, new ValidateAction(validateAction));
}
private static void registerMetaData() {
final MetaDataRegistrar registrar = MetaDataRegistrar.getInstance();
registrar.registerMetaData(
new AndFilter(
new NamespaceFilter(ProjectLoader.RNG_NAMESPACE),
new ClassFilter(XmlDocument.class)
),
RngNsDescriptor.class);
registrar.registerMetaData(
new ClassFilter(RncDocument.class),
RngNsDescriptor.class);
registrar.registerMetaData(new ElementFilter() {
public boolean isAcceptable(Object element, PsiElement context) {
if (element instanceof XmlTag) {
final XmlTag tag = (XmlTag)element;
final DomElement domElement = DomManager.getDomManager(tag.getProject()).getDomElement(tag);
return domElement instanceof RngDefine;
}
return false;
}
public boolean isClassAcceptable(Class hintClass) {
return XmlTag.class.isAssignableFrom(hintClass);
}
}, RngDefineMetaData.class);
}
public void disposeComponent() {
}
public Class[] getInspectionClasses() {
return new Class[]{
RngDomInspection.class,
UnusedDefineInspection.class
};
}
public class ResourceProvider implements StandardResourceProvider {
public void registerResources(ResourceRegistrar registrar) {
registrar.addStdResource(ProjectLoader.RNG_NAMESPACE, "resources/relaxng.rng", getClass());
registrar.addIgnoredResource("http://relaxng.org/ns/compatibility/annotations/1.0");
}
}
}
@@ -0,0 +1,42 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG;
import org.intellij.plugins.relaxNG.model.resolve.RelaxSymbolIndex;
import com.intellij.navigation.ChooseByNameContributor;
import com.intellij.navigation.NavigationItem;
import com.intellij.openapi.project.Project;
import java.util.Collection;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 24.10.2007
*/
public class GotoSymbolContributor implements ChooseByNameContributor {
public NavigationItem[] getItemsByName(String name, String pattern, Project project, boolean includeNonProjectItems) {
return RelaxSymbolIndex.getSymbolsByName(name, project, includeNonProjectItems);
}
public String[] getNames(Project project, boolean includeNonProjectItems) {
final Collection<String> names = RelaxSymbolIndex.getSymbolNames(project);
return names.toArray(new String[names.size()]);
}
}
@@ -0,0 +1,152 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.patterns.StringPattern;
import com.intellij.patterns.XmlNamedElementPattern;
import com.intellij.psi.AbstractElementManipulator;
import com.intellij.psi.PsiManager;
import com.intellij.psi.filters.position.PatternFilter;
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.xml.DomFileDescription;
import com.intellij.util.xml.DomManager;
import com.intellij.util.xml.highlighting.DomElementsAnnotator;
import com.intellij.xml.util.XmlUtil;
import org.intellij.plugins.relaxNG.compact.RncTokenTypes;
import org.intellij.plugins.relaxNG.compact.psi.RncFileReference;
import org.intellij.plugins.relaxNG.compact.psi.util.RenameUtil;
import org.intellij.plugins.relaxNG.model.annotation.ModelAnnotator;
import org.intellij.plugins.relaxNG.references.PrefixReferenceProvider;
import org.intellij.plugins.relaxNG.xml.dom.*;
import org.intellij.plugins.relaxNG.xml.dom.impl.RngDefineImpl;
import org.intellij.plugins.relaxNG.xml.dom.impl.RngGrammarImpl;
import org.intellij.plugins.relaxNG.xml.dom.impl.RngIncludeImpl;
import org.intellij.plugins.relaxNG.xml.dom.impl.RngRefImpl;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import static com.intellij.patterns.StandardPatterns.string;
import static com.intellij.patterns.XmlPatterns.*;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 16.07.2007
*/
public class ProjectLoader implements ProjectComponent {
public static final String RNG_NAMESPACE = "http://relaxng.org/ns/structure/1.0";
private static final XmlNamedElementPattern RNG_TAG_PATTERN = xmlTag().withNamespace(string().equalTo(RNG_NAMESPACE));
private static final XmlNamedElementPattern.XmlAttributePattern NAME_ATTR_PATTERN = xmlAttribute("name");
private static final StringPattern ELEMENT_OR_ATTRIBUTE_PATTERN = string().oneOf("element", "attribute");
private static final XmlNamedElementPattern.XmlAttributePattern NAME_PATTERN = NAME_ATTR_PATTERN.withParent(
RNG_TAG_PATTERN.withLocalName(ELEMENT_OR_ATTRIBUTE_PATTERN));
private final Project myProject;
public ProjectLoader(Project project) {
myProject = project;
}
@NonNls
@NotNull
public String getComponentName() {
return "RELAX-NG";
}
public void initComponent() {
registerFileDescriptions();
registerReferences();
}
private void registerReferences() {
final ReferenceProvidersRegistry registry = ReferenceProvidersRegistry.getInstance(myProject);
XmlUtil.registerXmlAttributeValueReferenceProvider(registry, new String[]{
"name"
}, new PatternFilter(xmlAttributeValue().withParent(NAME_PATTERN)), true, new PrefixReferenceProvider());
// final XmlAttributeValuePattern id = xmlAttributeValue().withParent(xmlAttribute()).with(IdRefProvider.HAS_ID_REF_TYPE);
// final XmlAttributeValuePattern idref = xmlAttributeValue().withParent(xmlAttribute()).with(IdRefProvider.HAS_ID_TYPE);
// registry.registerXmlAttributeValueReferenceProvider(null, new PatternFilter(or(id, idref)), false, new IdRefProvider());
}
@SuppressWarnings({ "deprecation" })
private void registerFileDescriptions() {
final DomManager mgr = DomManager.getDomManager(myProject);
mgr.registerFileDescription(new MyFileDescription<RngGrammar>(RngGrammar.class, "grammar"));
mgr.registerFileDescription(new MyFileDescription<RngElement>(RngElement.class, "element"));
mgr.registerFileDescription(new MyFileDescription<RngChoice>(RngChoice.class, "choice"));
mgr.registerFileDescription(new MyFileDescription<RngGroup>(RngGroup.class, "group"));
mgr.registerFileDescription(new MyFileDescription<RngInterleave>(RngInterleave.class, "interleave"));
}
public void disposeComponent() {
}
public void projectOpened() {
}
public void projectClosed() {
}
private static class MyFileDescription<T> extends DomFileDescription<T> {
public MyFileDescription(Class<T> elementClass, String rootTagName) {
super(elementClass, rootTagName);
registerNamespacePolicy("RELAX-NG", RNG_NAMESPACE);
registerImplementation(RngDefine.class, RngDefineImpl.class);
registerImplementation(RngGrammar.class, RngGrammarImpl.class);
registerImplementation(RngInclude.class, RngIncludeImpl.class);
registerImplementation(RngRef.class, RngRefImpl.class);
}
public boolean isAutomaticHighlightingEnabled() {
return true;
}
public DomElementsAnnotator createAnnotator() {
return new ModelAnnotator();
}
}
public static class RncFileReferenceManipulator extends AbstractElementManipulator<RncFileReference> {
public RncFileReference handleContentChange(RncFileReference element, TextRange range, String newContent) throws IncorrectOperationException {
final ASTNode node = element.getNode();
assert node != null;
final ASTNode literal = node.findChildByType(RncTokenTypes.LITERAL);
if (literal != null) {
assert range.equals(element.getReferenceRange());
final PsiManager manager = PsiManager.getInstance(element.getProject());
final ASTNode newChild = RenameUtil.createLiteralNode(manager, newContent);
literal.getTreeParent().replaceChild(literal, newChild);
}
return element;
}
@Override
public TextRange getRangeInElement(RncFileReference element) {
return element.getReferenceRange();
}
}
}
@@ -0,0 +1,148 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG;
import org.intellij.plugins.relaxNG.model.descriptors.CompositeDescriptor;
import org.intellij.plugins.relaxNG.model.descriptors.RngElementDescriptor;
import org.intellij.plugins.relaxNG.model.descriptors.RngXmlAttributeDescriptor;
import com.intellij.lang.documentation.DocumentationProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlTag;
import com.intellij.xml.XmlAttributeDescriptor;
import com.intellij.xml.XmlElementDescriptor;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import org.kohsuke.rngom.digested.DElementPattern;
import java.util.Collection;
import java.util.List;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 19.11.2007
*/
public class RngDocumentationProvider implements DocumentationProvider {
@NonNls
private static final String COMPATIBILITY_ANNOTATIONS_1_0 = "http://relaxng.org/ns/compatibility/annotations/1.0";
@Nullable
public String generateDoc(PsiElement element, PsiElement originalElement) {
final XmlElement c = PsiTreeUtil.getParentOfType(originalElement, XmlTag.class, XmlAttribute.class);
if (c instanceof XmlTag) {
final XmlTag xmlElement = (XmlTag)c;
final XmlElementDescriptor descriptor = xmlElement.getDescriptor();
if (descriptor instanceof CompositeDescriptor) {
final StringBuilder sb = new StringBuilder();
final CompositeDescriptor d = (CompositeDescriptor)descriptor;
final DElementPattern[] patterns = d.getElementPatterns();
for (DElementPattern pattern : patterns) {
final PsiElement psiElement = d.getDeclaration(pattern.getLocation());
if (psiElement instanceof XmlTag) {
if (sb.length() > 0) {
sb.append("<hr>");
}
sb.append(getDocumentationFromTag((XmlTag)psiElement, xmlElement.getLocalName(), "Element"));
}
}
return makeDocumentation(sb);
} else if (descriptor instanceof RngElementDescriptor) {
final RngElementDescriptor d = (RngElementDescriptor)descriptor;
final PsiElement declaration = d.getDeclaration();
if (declaration instanceof XmlTag) {
return makeDocumentation(getDocumentationFromTag((XmlTag)declaration, xmlElement.getLocalName(), "Element"));
}
}
} else if (c instanceof XmlAttribute) {
final XmlAttribute attribute = (XmlAttribute)c;
final XmlAttributeDescriptor descriptor = attribute.getDescriptor();
if (descriptor instanceof RngXmlAttributeDescriptor) {
final RngXmlAttributeDescriptor d = (RngXmlAttributeDescriptor)descriptor;
final StringBuilder sb = new StringBuilder();
final Collection<PsiElement> declaration = d.getDeclarations();
for (PsiElement psiElement : declaration) {
if (psiElement instanceof XmlTag) {
if (sb.length() > 0) {
sb.append("<hr>");
}
sb.append(getDocumentationFromTag((XmlTag)element, d.getName(), "Attribute"));
}
}
}
} else if (element instanceof XmlTag) {
return makeDocumentation(getDocumentationFromTag((XmlTag)element, ((XmlTag)element).getLocalName(), "Element"));
}
return null;
}
private static String makeDocumentation(StringBuilder sb) {
if (!sb.toString().startsWith("<html>")) {
sb.insert(0, "<html>");
sb.append("</html>");
}
return sb.toString().replaceAll("\n", "<br>");
}
private static StringBuilder getDocumentationFromTag(XmlTag tag, String localName, String kind) {
if (tag.getNamespace().equals(ProjectLoader.RNG_NAMESPACE)) {
final StringBuilder sb = new StringBuilder();
sb.append(kind).append(": <b>").append(localName).append("</b><br>");
final XmlTag[] docTags = tag.findSubTags("documentation", COMPATIBILITY_ANNOTATIONS_1_0);
for (XmlTag docTag : docTags) {
sb.append(docTag.getValue().getTrimmedText());
sb.append("\n");
}
final XmlTag nextTag = PsiTreeUtil.getNextSiblingOfType(tag, XmlTag.class);
if (nextTag != null) {
if ("documentation".equals(nextTag.getLocalName()) && COMPATIBILITY_ANNOTATIONS_1_0.equals(nextTag.getNamespace())) {
sb.append(nextTag.getValue().getTrimmedText());
}
}
return sb;
}
return null;
}
@Nullable
public PsiElement getDocumentationElementForLink(PsiManager psiManager, String link, PsiElement context) {
return null;
}
@Nullable
public PsiElement getDocumentationElementForLookupItem(PsiManager psiManager, Object object, PsiElement element) {
return null;
}
@Nullable
public String getQuickNavigateInfo(PsiElement element) {
return null;
}
public List<String> getUrlFor(PsiElement element, PsiElement originalElement) {
return null;
}
public int hashCode() {
return 0; // CompositeDocumentationProvider uses a HashSet that doesn't preserve order. We want to be the first one.
}
}
@@ -0,0 +1,135 @@
/*
* Copyright 2006 Sascha Weinreuter
*
* 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.plugins.relaxNG;
import com.intellij.ide.BrowserUtil;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.openapi.diagnostic.ErrorReportSubmitter;
import com.intellij.openapi.diagnostic.IdeaLoggingEvent;
import com.intellij.openapi.diagnostic.SubmittedReportInfo;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import java.awt.*;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class SimpleErrorReportSubmitter extends ErrorReportSubmitter {
public String getReportActionText() {
return "Error Report Information";
}
public SubmittedReportInfo submit(IdeaLoggingEvent[] events, Component parentComponent) {
final IdeaPluginDescriptor plugin = PluginManager.getPlugin(getPluginDescriptor().getPluginId());
assert plugin != null;
final String title = plugin.getName() + " - " + plugin.getVersion();
final String vendorEmail = plugin.getVendorEmail();
final String subject = title + " Exception";
final String mailto = "mailto:" + encode(vendorEmail) + "?Subject=" + encode(subject) /*+
"&body=" + encode("Stacktrace:\n" + events[0].getThrowableText())*/;
final String weblink = "http://www.intellij.net/forums/forum.jsp?forum=18";
final String website = plugin.getUrl();
final String font = new JLabel().getFont().getName();
String message = "<html><span style='font: " + font + "; font-size:smaller'>" +
"To report an exception, please post the exception stacktrace and a short description " +
"of how it can be reproduced to the IntelliJ " +
"<a href='" + weblink + "'>plugin web forum</a> or the corresponding newsgroup, " +
"and/or send an email containing that information to " +
"<a href='" + mailto + "'>" + vendorEmail + "</a>." +
(website != null ? "<br><br>Please also check the plugin's <a href='" + website + "'>website</a> for more information." : "") +
"</span></html>";
final JEditorPane pane = new JEditorPane("text/html", message);
pane.setEditable(false);
pane.setPreferredSize(new Dimension(410, website != null ? 110 : 80));
pane.addHyperlinkListener(new HyperlinkListener() {
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
BrowserUtil.launchBrowser(e.getURL().toExternalForm());
}
}
});
new MyMessageDialog(parentComponent, title, Messages.getErrorIcon(), pane).show();
return new SubmittedReportInfo(null, null, SubmittedReportInfo.SubmissionStatus.FAILED);
}
private String encode(String link) {
final String enc = System.getProperty("file.encoding");
try {
return URLEncoder.encode(link, enc).replaceAll("\\+", "%20");
} catch (UnsupportedEncodingException e) {
throw new Error(e);
}
}
private static class MyMessageDialog extends DialogWrapper {
protected JComponent myMessage;
protected Icon myIcon;
public MyMessageDialog(Component parent, String title, Icon icon, JComponent message) {
super(parent, false);
_init(title, message, icon);
}
private void _init(String title, JComponent message, Icon icon) {
setTitle(title);
myMessage = message;
myIcon = icon;
setButtonsAlignment(SwingUtilities.CENTER);
init();
myMessage.setBackground(getContentPane().getBackground());
}
protected Action[] createActions() {
return new Action[]{ getOKAction() };
}
protected JComponent createNorthPanel() {
JPanel panel = new JPanel(new BorderLayout(15, 0));
if (myIcon != null) {
JLabel iconLabel = new JLabel(myIcon);
Container container = new Container();
container.setLayout(new BorderLayout());
container.add(iconLabel, BorderLayout.NORTH);
panel.add(container, BorderLayout.WEST);
}
if (myMessage != null) {
panel.add(myMessage, BorderLayout.CENTER);
}
return panel;
}
@Nullable
protected JComponent createCenterPanel() {
return null;
}
}
}
@@ -0,0 +1,126 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact;
import org.intellij.plugins.relaxNG.compact.psi.*;
import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider;
import com.intellij.codeInsight.daemon.QuickFixProvider;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.lang.annotation.Annotation;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiPolyVariantReference;
import com.intellij.psi.PsiReference;
import org.jetbrains.annotations.NotNull;
import java.text.MessageFormat;
import java.util.List;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 10.08.2007
*/
public class ReferenceAnnotator extends RncElementVisitor implements Annotator {
private AnnotationHolder myHolder;
public synchronized void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder holder) {
myHolder = holder;
try {
psiElement.accept(this);
} finally {
myHolder = null;
}
}
@Override
public void visitInclude(RncInclude include) {
checkReferences(include.getReferences());
}
@Override
public void visitExternalRef(RncExternalRef ref) {
checkReferences(ref.getReferences());
}
@Override
public void visitRef(RncRef pattern) {
checkReferences(pattern.getReferences());
}
@Override
public void visitParentRef(RncParentRef pattern) {
checkReferences(pattern.getReferences());
}
@Override
public void visitName(RncName name) {
checkReferences(name.getReferences());
}
private void checkReferences(PsiReference[] references) {
for (PsiReference reference : references) {
if (!reference.isSoft()) {
if (reference.resolve() == null) {
if (reference instanceof PsiPolyVariantReference) {
final PsiPolyVariantReference pvr = (PsiPolyVariantReference)reference;
if (pvr.multiResolve(false).length == 0) {
addError(reference);
}
} else {
addError(reference);
}
}
}
}
}
private void addError(PsiReference reference) {
final TextRange rangeInElement = reference.getRangeInElement();
final TextRange range = TextRange.from(reference.getElement().getTextRange().getStartOffset()
+ rangeInElement.getStartOffset(), rangeInElement.getLength());
final Annotation annotation;
if (reference instanceof EmptyResolveMessageProvider) {
final String s = ((EmptyResolveMessageProvider)reference).getUnresolvedMessagePattern();
annotation = myHolder.createErrorAnnotation(range, s != null ?
MessageFormat.format(s, reference.getCanonicalText())
: "Cannot resolve symbol");
} else {
annotation = myHolder.createErrorAnnotation(range, "Cannot resolve symbol");
}
annotation.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
if (reference instanceof QuickFixProvider) {
final HighlightInfo info = new HighlightInfo(HighlightInfoType.WRONG_REF, annotation.getStartOffset(), annotation.getEndOffset(), "", null);
((QuickFixProvider)reference).registerQuickfix(info, reference);
final List<Pair<HighlightInfo.IntentionActionDescriptor,TextRange>> ranges = info.quickFixActionRanges;
if (ranges != null) {
for (Pair<HighlightInfo.IntentionActionDescriptor, TextRange> pair : ranges) {
annotation.registerFix(pair.first.getAction(), pair.second);
}
}
}
}
}
@@ -0,0 +1,137 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact;
import com.intellij.codeInsight.TailType;
import com.intellij.codeInsight.completion.CompletionContext;
import com.intellij.codeInsight.completion.CompletionData;
import com.intellij.codeInsight.completion.CompletionVariant;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementFactory;
import com.intellij.patterns.ElementPattern;
import com.intellij.patterns.PsiElementPattern;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.filters.AndFilter;
import com.intellij.psi.filters.ContextGetter;
import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.filters.position.PatternFilter;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.intellij.plugins.relaxNG.compact.psi.RncDecl;
import org.intellij.plugins.relaxNG.compact.psi.RncDefine;
import org.intellij.plugins.relaxNG.compact.psi.RncElement;
import org.intellij.plugins.relaxNG.compact.psi.RncGrammar;
import org.intellij.plugins.relaxNG.compact.psi.util.EscapeUtil;
import static com.intellij.patterns.PlatformPatterns.psiElement;
import static com.intellij.patterns.StandardPatterns.*;
public class RncCompletionData extends CompletionData {
public RncCompletionData() {
declareFinalScope(RncElement.class);
final CompletionVariant variant = new CompletionVariant(new AndFilter(
new ElementFilter() {
public boolean isAcceptable(Object element, PsiElement context) {
return true;
}
public boolean isClassAcceptable(Class hintClass) {
return PsiElement.class.isAssignableFrom(hintClass);
}
},
new PatternFilter(or(
psiElement().afterLeaf(psiElement(RncTokenTypes.KEYWORD_DEFAULT)),
not(
or(
psiElement().inside(psiElement(RncTokenTypes.LITERAL)),
psiElement().afterLeaf(psiElement().withElementType(RncTokenTypes.KEYWORDS))
)
)
))
));
variant.includeScopeClass(LeafPsiElement.class, true);
variant.addCompletion(new KeywordGetter());
registerVariant(variant);
}
private static class KeywordGetter implements ContextGetter {
private static final ElementPattern TOP_LEVEL =
not(psiElement().inside(psiElement(RncGrammar.class)
.inside(true, psiElement(RncGrammar.class))));
private static final PsiElementPattern DECL_PATTERN =
psiElement().inside(psiElement(RncDecl.class));
private static final PsiElementPattern DEFAULT_PATTERN =
DECL_PATTERN.afterLeaf(psiElement().withText("default"));
private static final ElementPattern DEFINE_PATTERN =
and(psiElement().withParent(RncDefine.class), psiElement().afterLeafSkipping(psiElement(PsiWhiteSpace.class), psiElement().withText("=")));
private static final String[] DECL_KEYWORDS = new String[]{ "default", "namespace", "datatypes" };
private static final String[] GRAMMAR_CONTENT_KEYWORDS = new String[]{ "include", "div", "start" };
private static final String[] PATTERN_KEYWORDS = new String[]{ "attribute", "element", "grammar",
"notAllowed", "text", "empty", "external", "parent", "list", "mixed" };
public Object[] get(PsiElement context, CompletionContext completionContext) {
return ContainerUtil.map2Array(doGetKeywords(context), LookupElement.class, new Function<String, LookupElement>() {
public LookupElement fun(String s) {
return LookupElementFactory.getInstance().createLookupElement(s).setTailType(TailType.SPACE).setBold();
}
});
}
private String[] doGetKeywords(PsiElement context) {
final PsiElement next = PsiTreeUtil.skipSiblingsForward(context, PsiWhiteSpace.class);
if (next != null && EscapeUtil.unescapeText(next).equals("=")) {
return new String[]{ "start" };
}
if (DEFAULT_PATTERN.accepts(context)) {
return new String[]{ "namespace" };
} else if (DECL_PATTERN.accepts(context)) {
return ArrayUtil.EMPTY_STRING_ARRAY;
} else if (context.getParent() instanceof RncDefine && context.getParent().getFirstChild() == context) {
if (DEFINE_PATTERN.accepts(context)) {
return ArrayUtil.EMPTY_STRING_ARRAY;
}
if (TOP_LEVEL.accepts(context)) {
if (!afterPattern(context)) {
return ArrayUtil.mergeArrays(DECL_KEYWORDS,
ArrayUtil.mergeArrays(GRAMMAR_CONTENT_KEYWORDS, PATTERN_KEYWORDS, String.class), String.class);
}
}
return GRAMMAR_CONTENT_KEYWORDS;
}
return PATTERN_KEYWORDS;
}
private boolean afterPattern(PsiElement context) {
// TODO: recognize all patterns
return PsiTreeUtil.getPrevSiblingOfType(context.getParent(), RncDefine.class) != null;
}
}
}
@@ -0,0 +1,56 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact;
import org.intellij.plugins.relaxNG.compact.psi.RncElement;
import com.intellij.lang.ASTNode;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.NotNullFunction;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
public class RncElementType extends IElementType {
public RncElementType(String name) {
super(name, RngCompactLanguage.INSTANCE);
}
}
class RncElementTypeEx<C extends RncElement> extends RncElementType implements NotNullFunction<ASTNode, C> {
private final Constructor<? extends C> myConstructor;
RncElementTypeEx(String name, Class<? extends C> clazz) {
super(name);
assert !clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers());
try {
myConstructor = clazz.getConstructor(ASTNode.class);
} catch (NoSuchMethodException e) {
throw new Error(e);
}
}
@NotNull
public final C fun(ASTNode node) {
try {
return myConstructor.newInstance(node);
} catch (Exception e) {
throw new Error(e);
}
}
}
@@ -0,0 +1,74 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact;
import org.intellij.plugins.relaxNG.compact.psi.*;
import org.intellij.plugins.relaxNG.compact.psi.impl.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.IFileElementType;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 01.08.2007
*/
public class RncElementTypes {
public static final IFileElementType FILE_ELEMENT_TYPE = new IFileElementType(RngCompactLanguage.INSTANCE);
public static final IElementType DOCUMENT = new RncElementTypeEx<RncDocument>("DOCUMENT", RncDocument.class);
public static final IElementType NS_DECL = new RncElementTypeEx<RncNsDecl>("NS_DECL", RncNsDeclImpl.class);
public static final IElementType DATATYPES_DECL = new RncElementTypeEx<RncDecl>("DATATYPES_DECL", RncDeclImpl.class);
public static final IElementType START = new RncElementType("START");
public static final IElementType DIV = new RncElementTypeEx<RncDiv>("DIV", RncDivImpl.class);
public static final IElementType INCLUDE = new RncElementTypeEx<RncInclude>("INCLUDE", RncIncludeImpl.class);
public static final IElementType NAME_CLASS = new RncElementType("NAME_CLASS");
public static final IElementType NAME_CLASS_CHOICE = new RncElementType("NAME_CLASS_CHOICE");
public static final IElementType EXCEPT_NAME_CLASS = new RncElementType("EXCEPT_NAME_CLASS");
public static final IElementType DEFINE = new RncElementTypeEx<RncDefine>("DEFINE", RncDefineImpl.class);
public static final IElementType PATTERN = new RncElementType("PATTERN");
public static final IElementType GROUP_PATTERN = new RncElementType("GROUP_PATTERN");
public static final IElementType GRAMMAR_PATTERN = new RncElementTypeEx<RncGrammar>("GRAMMAR_PATTERN", RncGrammarImpl.class);
public static final IElementType EMPTY_PATTERN = new RncElementType("EMPTY_PATTERN");
public static final IElementType TEXT_PATTERN = new RncElementType("TEXT_PATTERN");
public static final IElementType NOT_ALLOWED_PATTERN = new RncElementType("NOT_ALLOWED_PATTERN");
public static final IElementType EXTERNAL_REF = new RncElementTypeEx<RncExternalRef>("EXTERNAL_REF", RncExternalRefImpl.class);
public static final IElementType PARENT_REF = new RncElementTypeEx<RncParentRef>("PARENT_REF", RncParentRefImpl.class);
public static final IElementType REF_PATTERN = new RncElementTypeEx<RncRef>("REF_PATTERN", RncRefImpl.class);
public static final IElementType LIST_PATTERN = new RncElementType("LIST_PATTERN");
public static final IElementType MIXED_PATTERN = new RncElementType("MIXED_PATTERN");
public static final IElementType DATATYPE_PATTERN = new RncElementType("DATATYPE_PATTERN");
public static final IElementType PARAM = new RncElementType("PARAM");
public static final IElementType SEQUENCE = new RncElementType("SEQUENCE");
public static final IElementType INTERLEAVE = new RncElementType("INTERLEAVE");
public static final IElementType CHOICE = new RncElementType("CHOICE");
public static final IElementType OPTIONAL = new RncElementType("OPTIONAL");
public static final IElementType ZERO_OR_MORE = new RncElementType("ZERO_OR_MORE");
public static final IElementType ONE_OR_MORE = new RncElementType("ONE_OR_MORE");
public static final IElementType NAME = new RncElementTypeEx<RncName>("NAME", RncNameImpl.class);
public static final IElementType ANNOTATION = new RncElementTypeEx<RncAnnotation>("ANNOTATION", RncAnnotationImpl.class);
public static final IElementType ANNOTATION_ELEMENT = new RncElementTypeEx<RncAnnotation>("ANNOTATION_ELEMENT", RncAnnotationImpl.class);
public static final IElementType FORWARD_ANNOTATION = new RncElementTypeEx<RncAnnotation>("FORWARD_ANNOTATION", RncAnnotationImpl.class);
}
@@ -0,0 +1,83 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeConsumer;
import com.intellij.openapi.fileTypes.FileTypeFactory;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.util.IconLoader;
import com.intellij.util.PairConsumer;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 01.08.2007
*/
public class RncFileType extends LanguageFileType {
public static final String RNC_EXT = "rnc";
private static FileType INSTANCE;
private RncFileType() {
super(RngCompactLanguage.INSTANCE);
}
@NotNull
@NonNls
public String getName() {
return "RNG Compact";
}
@NotNull
public String getDescription() {
return "RELAX NG Compact Syntax";
}
@NotNull
@NonNls
public String getDefaultExtension() {
return "rnc";
}
@Nullable
public Icon getIcon() {
return IconLoader.findIcon("/fileTypes/text.png");
}
public static synchronized FileType getInstance() {
if (INSTANCE == null) {
INSTANCE = new RncFileType();
}
return INSTANCE;
}
public static class Factory extends FileTypeFactory {
public void createFileTypes(@NotNull FileTypeConsumer fileTypeConsumer) {
fileTypeConsumer.consume(getInstance(), RNC_EXT);
}
public void createFileTypes(@NotNull PairConsumer<FileType, String> consumer) {
consumer.consume(getInstance(), RNC_EXT);
}
}
}
@@ -0,0 +1,77 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact;
import org.intellij.plugins.relaxNG.compact.lexer.CompactSyntaxLexerAdapter;
import com.intellij.lexer.Lexer;
import com.intellij.openapi.editor.HighlighterColors;
import com.intellij.openapi.editor.SyntaxHighlighterColors;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.fileTypes.SyntaxHighlighterBase;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 04.08.2007
*/
public class RncHighlighter extends SyntaxHighlighterBase {
@NotNull
public Lexer getHighlightingLexer() {
return new CompactSyntaxLexerAdapter();
}
private static final Map<IElementType, TextAttributesKey> ourMap1;
static {
ourMap1 = new HashMap<IElementType, TextAttributesKey>();
fillMap(ourMap1, RncTokenTypes.KEYWORDS, SyntaxHighlighterColors.KEYWORD);
fillMap(ourMap1, RncTokenTypes.OPERATORS, SyntaxHighlighterColors.OPERATION_SIGN);
fillMap(ourMap1, RncTokenTypes.STRINGS, SyntaxHighlighterColors.STRING);
ourMap1.put(RncTokenTypes.LBRACE, SyntaxHighlighterColors.BRACES);
ourMap1.put(RncTokenTypes.RBRACE, SyntaxHighlighterColors.BRACES);
ourMap1.put(RncTokenTypes.LBRACKET, SyntaxHighlighterColors.BRACKETS);
ourMap1.put(RncTokenTypes.RBRACKET, SyntaxHighlighterColors.BRACKETS);
ourMap1.put(RncTokenTypes.LPAREN, SyntaxHighlighterColors.PARENTHS);
ourMap1.put(RncTokenTypes.RPAREN, SyntaxHighlighterColors.PARENTHS);
ourMap1.put(RncTokenTypes.COMMA, SyntaxHighlighterColors.COMMA);
fillMap(ourMap1, RncTokenTypes.DOC_TOKENS, SyntaxHighlighterColors.DOC_COMMENT);
fillMap(ourMap1, RncTokenTypes.COMMENTS, SyntaxHighlighterColors.LINE_COMMENT);
fillMap(ourMap1, RncTokenTypes.IDENTIFIERS, CodeInsightColors.LOCAL_VARIABLE_ATTRIBUTES);
ourMap1.put(RncTokenTypes.ILLEGAL_CHAR, HighlighterColors.BAD_CHARACTER);
}
@NotNull
public TextAttributesKey[] getTokenHighlights(IElementType tokenType) {
return pack(ourMap1.get(tokenType));
}
}
@@ -0,0 +1,103 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact;
import org.intellij.plugins.relaxNG.compact.lexer.CompactSyntaxLexerAdapter;
import org.intellij.plugins.relaxNG.compact.parser.RncParser;
import org.intellij.plugins.relaxNG.compact.psi.RncElementVisitor;
import org.intellij.plugins.relaxNG.compact.psi.impl.RncElementImpl;
import org.intellij.plugins.relaxNG.compact.psi.impl.RncFileImpl;
import com.intellij.lang.ASTNode;
import com.intellij.lang.ParserDefinition;
import com.intellij.lang.PsiParser;
import com.intellij.lexer.Lexer;
import com.intellij.openapi.project.Project;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.IFileElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.util.NotNullFunction;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 10.08.2007
*/
public class RncParserDefinition implements ParserDefinition {
@NotNull
public Lexer createLexer(Project project) {
return new CompactSyntaxLexerAdapter();
}
public PsiParser createParser(Project project) {
return new RncParser();
}
public IFileElementType getFileNodeType() {
return RncElementTypes.FILE_ELEMENT_TYPE;
}
@NotNull
public TokenSet getWhitespaceTokens() {
return TokenSet.create(TokenType.WHITE_SPACE);
}
@NotNull
public TokenSet getCommentTokens() {
return TokenSet.orSet(RncTokenTypes.COMMENTS, RncTokenTypes.DOC_TOKENS);
}
@NotNull
public TokenSet getStringLiteralElements() {
return TokenSet.create(RncTokenTypes.LITERAL);
}
@NotNull
@SuppressWarnings({ "unchecked" })
public PsiElement createElement(ASTNode node) {
final IElementType type = node.getElementType();
if (type instanceof NotNullFunction) {
return ((NotNullFunction<ASTNode, PsiElement>)type).fun(node);
}
return new MyRncElement(node);
}
public PsiFile createFile(FileViewProvider viewProvider) {
return new RncFileImpl(viewProvider);
}
public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) {
return SpaceRequirements.MAY;
}
private static class MyRncElement extends RncElementImpl {
public MyRncElement(ASTNode node) {
super(node);
}
public void accept(@NotNull RncElementVisitor visitor) {
visitor.visitElement(this);
}
}
}
@@ -0,0 +1,205 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull;
import gnu.trove.TIntObjectHashMap;
import gnu.trove.TObjectProcedure;
import org.kohsuke.rngom.parse.compact.CompactSyntaxConstants;
import java.lang.reflect.Field;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 04.08.2007
*/
public class RncTokenTypes {
private static final TIntObjectHashMap<IElementType> ourTokenTypes = new TIntObjectHashMap<IElementType>();
static {
assert RngCompactLanguage.INSTANCE != null;
try {
final Field[] fields = CompactSyntaxConstants.class.getFields();
for (Field field : fields) {
final String name = field.getName();
if (name.equals("DEFAULT")) break;
if (int.class.isAssignableFrom(field.getType())) {
Integer i = (Integer)field.get(null);
ourTokenTypes.put(i, new RncElementType(name));
}
}
final String[] tokens = CompactSyntaxConstants.tokenImage;
for (int i = 0; i < tokens.length; i++) {
String token = tokens[i];
if (token.matches("\"\\w*\"")) {
token = "KEYWORD_" + token.substring(1, token.length() - 1).toUpperCase();
} else if (token.matches("\".*\"")) {
token = token.substring(1, token.length() - 1);
}
if (ourTokenTypes.get(i) == null) {
ourTokenTypes.put(i, new RncElementType(token));
}
}
} catch (IllegalAccessException e) {
throw new Error(e);
}
}
@NotNull
public static IElementType get(int i) {
assert !ourTokenTypes.isEmpty();
final IElementType type = ourTokenTypes.get(i);
assert type != null : "Unknown token kind: " + i;
return type;
}
@NotNull
private static IElementType get(final String name) {
assert !ourTokenTypes.isEmpty();
final Ref<IElementType> ref = new Ref<IElementType>();
ourTokenTypes.forEachValue(new TObjectProcedure<IElementType>() {
public boolean execute(IElementType iElementType) {
if (iElementType.toString().equals(name)) {
ref.set(iElementType);
return false;
}
return true;
}
});
return ref.get();
}
private static final IElementType WS = get(CompactSyntaxConstants.WS);
public static final TokenSet WHITESPACE = TokenSet.create(WS);
public static final IElementType ILLEGAL_CHAR = get(CompactSyntaxConstants.ILLEGAL_CHAR);
public static final IElementType LBRACE = get("{");
public static final IElementType RBRACE = get("}");
public static final IElementType LBRACKET = get("[");
public static final IElementType RBRACKET = get("]");
public static final IElementType LPAREN = get("(");
public static final IElementType RPAREN = get(")");
public static final IElementType GTGT = get(CompactSyntaxConstants.FANNOTATE);
public static final TokenSet BRACES = TokenSet.create(LBRACE, RBRACE);
public static final IElementType EQ = get("=");
public static final IElementType PLUS = get("+");
public static final IElementType MINUS = get("-");
public static final IElementType STAR = get("*");
public static final IElementType AND = get("&");
public static final IElementType PIPE = get("|");
public static final IElementType QUEST = get("?");
public static final IElementType PREFIXED_NAME = get(CompactSyntaxConstants.PREFIXED_NAME);
public static final IElementType PREFIXED_STAR = get(CompactSyntaxConstants.PREFIX_STAR);
public static final IElementType CHOICE_EQ = get("|=");
public static final IElementType INTERLEAVE_EQ = get("&=");
public static final IElementType COMMA = get(",");
public static final TokenSet BINARY_OPS = TokenSet.create(
COMMA, PIPE, AND
);
public static final TokenSet QUANTIFIER_OPS = TokenSet.create(
PLUS, STAR, QUEST
);
public static final IElementType DOC = get(CompactSyntaxConstants.DOCUMENTATION);
public static final TokenSet DOC_TOKENS = TokenSet.create(
DOC,
get(CompactSyntaxConstants.DOCUMENTATION_AFTER_SINGLE_LINE_COMMENT),
get(CompactSyntaxConstants.DOCUMENTATION_CONTINUE)
);
public static final IElementType COMMENT = get(CompactSyntaxConstants.SINGLE_LINE_COMMENT);
public static final TokenSet COMMENTS = TokenSet.create(
COMMENT,
get(CompactSyntaxConstants.SINGLE_LINE_COMMENT_CONTINUE)
);
public static final IElementType ESCAPED_IDENTIFIER = get(CompactSyntaxConstants.ESCAPED_IDENTIFIER);
public static final TokenSet IDENTIFIERS = TokenSet.create(
get(CompactSyntaxConstants.IDENTIFIER),
ESCAPED_IDENTIFIER
);
public static final TokenSet OPERATORS = TokenSet.orSet(TokenSet.create(
CHOICE_EQ, INTERLEAVE_EQ), BINARY_OPS, QUANTIFIER_OPS);
public static final IElementType LITERAL = get(CompactSyntaxConstants.LITERAL);
public static final TokenSet STRINGS = TokenSet.create(LITERAL);
static final TokenSet READABLE_TEXT = TokenSet.orSet(
DOC_TOKENS, COMMENTS,
TokenSet.create(LITERAL));
public static final IElementType KEYWORD_ElEMENT = get("KEYWORD_ELEMENT");
public static final IElementType KEYWORD_ATTRIBUTE = get("KEYWORD_ATTRIBUTE");
public static final IElementType KEYWORD_NAMESPACE = get("KEYWORD_NAMESPACE");
public static final IElementType KEYWORD_LIST = get("KEYWORD_LIST");
public static final IElementType KEYWORD_MIXED = get("KEYWORD_MIXED");
public static final IElementType KEYWORD_EMPTY = get("KEYWORD_EMPTY");
public static final IElementType KEYWORD_GRAMMAR = get("KEYWORD_GRAMMAR");
public static final IElementType KEYWORD_TEXT = get("KEYWORD_TEXT");
public static final IElementType KEYWORD_PARENT = get("KEYWORD_PARENT");
public static final IElementType KEYWORD_EXTERNAL = get("KEYWORD_LIST");
public static final IElementType KEYWORD_NOT_ALLOWED = get("KEYWORD_NOTALLOWED");
public static final IElementType KEYWORD_START = get("KEYWORD_START");
public static final IElementType KEYWORD_INCLUDE = get("KEYWORD_INCLUDE");
public static final IElementType KEYWORD_DEFAULT = get("KEYWORD_DEFAULT");
public static final IElementType KEYWORD_INHERIT = get("KEYWORD_INHERIT");
public static final IElementType KEYWORD_STRING = get("KEYWORD_STRING");
public static final IElementType KEYWORD_TOKEN = get("KEYWORD_TOKEN");
public static final IElementType KEYWORD_DATATYPES = get("KEYWORD_DATATYPES");
public static final IElementType KEYWORD_DIV = get("KEYWORD_DIV");
public static final TokenSet KEYWORDS = TokenSet.create(
KEYWORD_ATTRIBUTE,
KEYWORD_DATATYPES,
KEYWORD_DEFAULT,
KEYWORD_DIV,
KEYWORD_ElEMENT,
KEYWORD_EMPTY,
KEYWORD_EXTERNAL,
KEYWORD_GRAMMAR,
KEYWORD_INCLUDE,
KEYWORD_INHERIT,
KEYWORD_LIST,
KEYWORD_MIXED,
KEYWORD_NAMESPACE,
KEYWORD_NOT_ALLOWED,
KEYWORD_PARENT,
KEYWORD_START,
KEYWORD_STRING,
KEYWORD_TEXT,
KEYWORD_TOKEN
);
public static final TokenSet IDENTIFIER_OR_KEYWORD = TokenSet.orSet(KEYWORDS, IDENTIFIERS);
}
@@ -0,0 +1,164 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact;
import org.intellij.plugins.relaxNG.compact.psi.RncDefine;
import org.intellij.plugins.relaxNG.compact.psi.RncElement;
import org.intellij.plugins.relaxNG.compact.psi.util.EscapeUtil;
import org.intellij.plugins.relaxNG.compact.psi.util.RenameUtil;
import com.intellij.lang.BracePair;
import com.intellij.lang.Commenter;
import com.intellij.lang.Language;
import com.intellij.lang.PairedBraceMatcher;
import com.intellij.lang.documentation.DocumentationProvider;
import com.intellij.lang.refactoring.NamesValidator;
import com.intellij.openapi.fileTypes.SingleLazyInstanceSyntaxHighlighterFactory;
import com.intellij.openapi.fileTypes.SyntaxHighlighter;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 01.08.2007
*/
public class RngCompactLanguage extends Language {
public static final String ID = "RELAX-NG";
public static final RngCompactLanguage INSTANCE = new RngCompactLanguage();
private RngCompactLanguage() {
super(ID);
}
public static class MyCommenter implements Commenter {
@Nullable
public String getLineCommentPrefix() {
return "#";
}
@Nullable
public String getBlockCommentPrefix() {
return null;
}
@Nullable
public String getBlockCommentSuffix() {
return null;
}
public String getCommentedBlockCommentPrefix() {
return null;
}
public String getCommentedBlockCommentSuffix() {
return null;
}
}
public static class MyPairedBraceMatcher implements PairedBraceMatcher {
private BracePair[] myBracePairs;
public BracePair[] getPairs() {
if (myBracePairs == null) {
myBracePairs = new BracePair[]{
new BracePair(RncTokenTypes.LBRACE, RncTokenTypes.RBRACE, true),
new BracePair(RncTokenTypes.LPAREN, RncTokenTypes.RPAREN, false),
new BracePair(RncTokenTypes.LBRACKET, RncTokenTypes.RBRACKET, false),
};
}
return myBracePairs;
}
public boolean isPairedBracesAllowedBeforeType(@NotNull IElementType lbraceType, @Nullable IElementType contextType) {
return false;
}
public int getCodeConstructStart(PsiFile file, int openingBraceOffset) {
// TODO
return openingBraceOffset;
}
}
public static class MyNamesValidator implements NamesValidator {
public boolean isKeyword(String name, Project project) {
return RenameUtil.isKeyword(PsiManager.getInstance(project), name);
}
public boolean isIdentifier(String name, Project project) {
return RenameUtil.isIdentifier(PsiManager.getInstance(project), name);
}
}
public static class MyDocumentationProvider implements DocumentationProvider {
@Nullable
public String getQuickNavigateInfo(PsiElement element) {
return null;
}
public List<String> getUrlFor(PsiElement element, PsiElement originalElement) {
return null;
}
@Nullable
public String generateDoc(PsiElement element, PsiElement originalElement) {
if (element instanceof RncElement) {
PsiElement comment = element.getPrevSibling();
while (comment instanceof PsiWhiteSpace) {
comment = comment.getPrevSibling();
}
if (comment instanceof PsiComment) {
final StringBuilder sb = new StringBuilder();
do {
sb.insert(0, EscapeUtil.unescapeText(comment).replaceAll("\n?##?", "") + "<br>");
comment = comment.getPrevSibling();
} while (comment instanceof PsiComment);
if (element instanceof RncDefine) {
sb.insert(0, "Define: <b>" + ((RncDefine)element).getName() + "</b><br>");
}
return sb.toString();
}
}
return null;
}
@Nullable
public PsiElement getDocumentationElementForLookupItem(PsiManager psiManager, Object object, PsiElement element) {
return null;
}
@Nullable
public PsiElement getDocumentationElementForLink(PsiManager psiManager, String link, PsiElement context) {
return null;
}
}
public static class MySyntaxHighlighterFactory extends SingleLazyInstanceSyntaxHighlighterFactory {
@NotNull
protected SyntaxHighlighter createHighlighter() {
return new RncHighlighter();
}
}
}
@@ -0,0 +1,158 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact.folding;
import org.intellij.plugins.relaxNG.compact.RncElementTypes;
import org.intellij.plugins.relaxNG.compact.RncTokenTypes;
import org.intellij.plugins.relaxNG.compact.psi.RncAnnotation;
import org.intellij.plugins.relaxNG.compact.psi.RncName;
import org.intellij.plugins.relaxNG.compact.psi.util.EscapeUtil;
import com.intellij.codeInsight.folding.CodeFoldingSettings;
import com.intellij.lang.ASTNode;
import com.intellij.lang.folding.FoldingBuilder;
import com.intellij.lang.folding.FoldingDescriptor;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 10.08.2007
*/
public class RncFoldingBuilder implements FoldingBuilder {
@NotNull
public FoldingDescriptor[] buildFoldRegions(@NotNull ASTNode node, @NotNull Document document) {
final ArrayList<FoldingDescriptor> regions = new ArrayList<FoldingDescriptor>();
process(node, document, regions);
return regions.size() > 0
? regions.toArray(new FoldingDescriptor[regions.size()])
: FoldingDescriptor.EMPTY;
}
public String getPlaceholderText(@NotNull ASTNode node) {
final IElementType type = node.getElementType();
if (type == RncTokenTypes.LBRACE) {
return "{ ... }";
} else if (isCommentLike(type)) {
return "# ...";
} else if (isAnnotation(type)) {
final RncName element = ((RncAnnotation)node.getPsi()).getNameElement();
if (element != null) {
final ASTNode n = element.getNode();
assert n != null;
return EscapeUtil.unescapeText(n) + " [ ... ]";
}
return "[ ... ]";
} else {
return "...";
}
}
private static boolean isAnnotation(IElementType type) {
return RncElementTypes.ANNOTATION == type || RncElementTypes.ANNOTATION_ELEMENT == type || RncElementTypes.FORWARD_ANNOTATION == type;
}
private static boolean isCommentLike(IElementType type) {
return RncTokenTypes.COMMENTS.contains(type) || RncTokenTypes.DOC_TOKENS.contains(type);
}
public boolean isCollapsedByDefault(@NotNull ASTNode node) {
return isCommentLike(node.getElementType()) && CodeFoldingSettings.getInstance().COLLAPSE_DOC_COMMENTS;
}
private static void process(@Nullable ASTNode node, Document document, ArrayList<FoldingDescriptor> regions) {
if (node == null) {
return;
}
final ASTNode[] braces = node.getChildren(RncTokenTypes.BRACES);
if (braces.length == 2) {
final ASTNode lbrace = braces[0];
final ASTNode rbrace = braces[1];
if (shouldFold(lbrace, rbrace, document)) {
final TextRange range = new TextRange(lbrace.getStartOffset(), rbrace.getTextRange().getEndOffset());
regions.add(new FoldingDescriptor(lbrace, range));
}
} else if (isAnnotation(node.getElementType())) {
if (isOnDifferentLine(node.getFirstChildNode(), node.getLastChildNode(), document)) {
regions.add(new FoldingDescriptor(node, node.getTextRange()));
}
}
node = node.getFirstChildNode();
while (node != null) {
node = checkNodeAndSiblings(node, RncTokenTypes.DOC_TOKENS, regions, document);
node = checkNodeAndSiblings(node, RncTokenTypes.COMMENTS, regions, document);
process(node, document, regions);
if (node != null) {
node = node.getTreeNext();
}
}
}
@Nullable
private static ASTNode checkNodeAndSiblings(@Nullable ASTNode node, TokenSet tokens, ArrayList<FoldingDescriptor> regions, Document document) {
if (node != null && tokens.contains(node.getElementType())) {
final ASTNode start = node;
ASTNode end = start;
node = node.getTreeNext();
if (node != null) {
do {
end = node;
node = node.getTreeNext();
} while (node != null && tokens.contains(node.getElementType()));
}
if (end != start) {
while (end.getPsi() instanceof PsiWhiteSpace) {
end = end.getTreePrev();
}
if (isOnDifferentLine(start, end, document)) {
regions.add(new FoldingDescriptor(start, new TextRange(start.getStartOffset(), end.getTextRange().getEndOffset())));
}
}
}
return node;
}
private static boolean shouldFold(ASTNode first, ASTNode second, Document document) {
if (first.getElementType() != RncTokenTypes.LBRACE) {
return false;
} else if (second.getElementType() != RncTokenTypes.RBRACE) {
return false;
} else {
return isOnDifferentLine(first, second, document);
}
}
private static boolean isOnDifferentLine(ASTNode first, ASTNode second, Document document) {
return document.getLineNumber(first.getStartOffset()) != document.getLineNumber(second.getStartOffset());
}
}
@@ -0,0 +1,127 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact.formatting;
import org.intellij.plugins.relaxNG.compact.RncElementTypes;
import org.intellij.plugins.relaxNG.compact.RncTokenTypes;
import org.intellij.plugins.relaxNG.compact.psi.RncDecl;
import org.intellij.plugins.relaxNG.compact.psi.RncDefine;
import org.intellij.plugins.relaxNG.compact.psi.RncFile;
import org.intellij.plugins.relaxNG.compact.psi.RncGrammar;
import org.intellij.plugins.relaxNG.compact.psi.impl.RncDocument;
import com.intellij.formatting.*;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
class RncBlock implements Block {
private final ASTNode myNode;
public RncBlock(ASTNode element) {
myNode = element;
}
@NotNull
public TextRange getTextRange() {
return myNode.getTextRange();
}
@NotNull
public List<Block> getSubBlocks() {
final List<Block> list = new ArrayList<Block>();
ASTNode node = myNode.getFirstChildNode();
while (node != null) {
if (!RncTokenTypes.WHITESPACE.contains(node.getElementType()) && node.getTextLength() > 0) {
list.add(new RncBlock(node));
}
node = node.getTreeNext();
}
return list;
}
@Nullable
public Wrap getWrap() {
// TODO
return null;
}
@Nullable
public Indent getIndent() {
if (isTopLevel()) {
return Indent.getAbsoluteNoneIndent();
} else if (myNode.getTreeParent().getPsi() instanceof RncGrammar && !RncTokenTypes.BRACES.contains(myNode.getElementType())) {
// TODO: fix block psi
return Indent.getNormalIndent();
}
return null;
}
private boolean isTopLevel() {
final PsiElement parent = myNode.getTreeParent().getPsi();
return parent instanceof RncDocument ||
parent instanceof RncFile ||
parent instanceof RncGrammar && parent.getParent() instanceof RncDocument;
}
@Nullable
public Alignment getAlignment() {
// TODO
return null;
}
@Nullable
public Spacing getSpacing(Block child1, Block child2) {
final ASTNode lnode = ((RncBlock)child1).myNode;
final PsiElement lpsi = lnode.getPsi();
final PsiElement rpsi = ((RncBlock)child2).myNode.getPsi();
if (lpsi instanceof RncDecl && rpsi instanceof RncDecl) {
return makeNewline();
}
if ((lpsi instanceof RncDecl || lpsi instanceof RncDefine ||
lnode.getElementType() == RncElementTypes.START) &&
(rpsi instanceof RncDefine || rpsi instanceof RncGrammar)) {
return makeNewline();
}
return null;
}
private static Spacing makeNewline() {
return Spacing.createSpacing(0, Integer.MAX_VALUE, 1, true, 100);
}
@NotNull
public ChildAttributes getChildAttributes(int newChildIndex) {
return new ChildAttributes(null, null);
}
public boolean isIncomplete() {
// TODO
return false;
}
public boolean isLeaf() {
// TODO
return false;
}
}
@@ -0,0 +1,39 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact.formatting;
import com.intellij.formatting.FormattingModel;
import com.intellij.formatting.FormattingModelBuilder;
import com.intellij.formatting.FormattingModelProvider;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import org.jetbrains.annotations.NotNull;
public class RncFormattingModelBuilder implements FormattingModelBuilder {
@NotNull
public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) {
return FormattingModelProvider.createFormattingModelForPsiFile(element.getContainingFile(), new RncBlock(element.getNode()), settings);
}
public TextRange getRangeAffectingIndent(PsiFile file, int offset, ASTNode elementAtOffset) {
// TODO
return null;
}
}
@@ -0,0 +1,258 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact.lexer;
import org.intellij.plugins.relaxNG.compact.RncTokenTypes;
import com.intellij.lexer.LexerBase;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.text.CharArrayCharSequence;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.Nullable;
import gnu.trove.TIntIntHashMap;
import org.kohsuke.rngom.parse.compact.CompactSyntaxConstants;
import org.kohsuke.rngom.parse.compact.CompactSyntaxTokenManager;
import org.kohsuke.rngom.parse.compact.Token;
import org.kohsuke.rngom.parse.compact.TokenMgrError;
import java.io.CharArrayReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Field;
import java.util.LinkedList;
/**
* An adapter to use the lexer ("TokenManager") generated from a javacc grammar.
*
* Not sure if it was easier to write this than hacking my own lexer...
*/
public class CompactSyntaxLexerAdapter extends LexerBase {
private static final Logger LOG = Logger.getInstance(CompactSyntaxLexerAdapter.class.getName());
private static final Field myStateField;
static {
try {
myStateField = CompactSyntaxTokenManager.class.getDeclaredField("curLexState");
myStateField.setAccessible(true);
} catch (NoSuchFieldException e) {
throw new Error(e);
}
}
private static final Token START = new Token();
private CompactSyntaxTokenManager myLexer;
private final LinkedList<Token> myTokenQueue = new LinkedList<Token>();
private Token myCurrentToken;
private int myCurrentOffset;
private int myCurrentEnd;
private IElementType myCurrentTokenType;
private CharSequence myBuffer;
private int myEndOffset;
private TIntIntHashMap myLengthMap;
public void advance() {
try {
myCurrentToken = nextToken();
myCurrentOffset = myCurrentEnd;
if (myCurrentToken != null) {
myCurrentEnd = myCurrentOffset + myCurrentToken.image.length();
for (int i = myCurrentOffset; i < myCurrentEnd; i++) {
myCurrentEnd += myLengthMap.get(i);
}
if (myCurrentToken.kind == CompactSyntaxConstants.EOF) {
assert myCurrentOffset == myEndOffset : "actual: " + myCurrentOffset + ", expected: " + myEndOffset;
myCurrentToken = null;
}
}
// if (myCurrentToken != null) {
// System.out.println("token = <" + RncTokenTypes.get(myCurrentToken.kind).toString() + "> [" + myCurrentToken.image + "]");
// }
} catch (TokenMgrError e) {
LOG.error(e);
myCurrentToken = null;
}
if (myCurrentToken == null) {
myCurrentTokenType = null;
} else {
myCurrentTokenType = RncTokenTypes.get(myCurrentToken.kind);
// collapse whitespace tokens into TokenType.WHITE_SPACE [IDEA-12106]
if (RncTokenTypes.WHITESPACE.contains(myCurrentTokenType)) {
myCurrentTokenType = TokenType.WHITE_SPACE;
}
}
}
private Token nextToken() {
if (myTokenQueue.size() > 0) {
return myTokenQueue.removeFirst();
}
final Token t = myLexer.getNextToken();
if (t.specialToken != null) {
myTokenQueue.addFirst(t);
for (Token s = t.specialToken; s != null; s = s.specialToken) {
myTokenQueue.addFirst(s);
}
return myTokenQueue.removeFirst();
} else {
return t;
}
}
@Deprecated
public char[] getBuffer() {
return CharArrayUtil.fromSequence(myBuffer);
}
@Override
public CharSequence getBufferSequence() {
return myBuffer;
}
public int getBufferEnd() {
return myEndOffset;
}
public int getState() {
try {
return (Integer)myStateField.get(myLexer);
} catch (Exception e) {
return -1;
}
}
public int getTokenEnd() {
return myCurrentEnd;
}
public int getTokenStart() {
return myCurrentToken == null ? 0 : myCurrentOffset;
}
@Nullable
public IElementType getTokenType() {
if (myCurrentToken == null) {
return null;
} else {
return myCurrentTokenType;
}
}
@Deprecated
public void start(char[] buffer, int startOffset, int endOffset, int initialState) {
myBuffer = new CharArrayCharSequence(buffer, startOffset, endOffset);
final CharArrayReader reader = new CharArrayReader(buffer, startOffset, endOffset - startOffset);
init(startOffset, endOffset, reader, initialState);
}
public void start(CharSequence buffer, int startOffset, int endOffset, int initialState) {
myBuffer = buffer;
final Reader reader = new CharSequenceReader(buffer, startOffset, endOffset);
init(startOffset, endOffset, reader, initialState);
}
private void init(int startOffset, int endOffset, Reader reader, int initialState) {
myEndOffset = endOffset;
myLengthMap = new TIntIntHashMap();
final EscapePreprocessor preprocessor = new EscapePreprocessor(reader, startOffset, myLengthMap);
myLexer = new CompactSyntaxTokenManager(new SimpleCharStream(preprocessor, 1, 1), initialState);
myCurrentToken = START;
myCurrentOffset = startOffset;
myCurrentEnd = startOffset;
myTokenQueue.clear();
advance();
}
public static void main(String[] args) throws IOException {
final CompactSyntaxLexerAdapter lexer = new CompactSyntaxLexerAdapter();
lexer.start(new CharArrayCharSequence(FileUtil.adaptiveLoadText(new FileReader(args[0]))));
while (lexer.getTokenType() != null) {
System.out.println("token = " + lexer.getTokenType());
final int start = lexer.getTokenStart();
System.out.println("start = " + start);
final int end = lexer.getTokenEnd();
System.out.println("end = " + end);
final CharSequence t = lexer.getBufferSequence().subSequence(start, end);
System.out.println("t = " + t);
lexer.advance();
}
}
// adapted from com.intellij.util.text.CharSequenceReader with start- and endOffset support
static class CharSequenceReader extends Reader {
private final CharSequence myText;
private final int myEndOffset;
private int myCurPos;
public CharSequenceReader(final CharSequence text, int startOffset, int endOffset) {
myText = text;
myEndOffset = endOffset;
myCurPos = startOffset;
}
public void close() {
}
public int read(char[] cbuf, int off, int len) {
if ((off < 0) || (off > cbuf.length) || (len < 0) || ((off + len) > cbuf.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
if (myText instanceof CharArrayCharSequence) { // Optimization
final int readChars = ((CharArrayCharSequence)myText).readCharsTo(myCurPos, cbuf, off, len);
if (readChars < 0) return -1;
myCurPos += readChars;
return readChars;
}
int charsToCopy = Math.min(len, myEndOffset - myCurPos);
if (charsToCopy <= 0) return -1;
for (int n = 0; n < charsToCopy; n++) {
cbuf[n + off] = myText.charAt(n + myCurPos);
}
myCurPos += charsToCopy;
return charsToCopy;
}
public int read() {
if (myCurPos >= myEndOffset) return -1;
return myText.charAt(myCurPos++);
}
}
}
@@ -0,0 +1,140 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact.lexer;
import gnu.trove.TIntArrayList;
import gnu.trove.TIntIntHashMap;
import org.kohsuke.rngom.util.Utf16;
import java.io.FilterReader;
import java.io.IOException;
import java.io.Reader;
/**
* A reader that deals with escape sequences in RNC files (\x{xx}) and keeps track of their positions to build correct
* token ranges in the lexer.
* <p/>
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 05.08.2007
*/
class EscapePreprocessor extends FilterReader {
private final TIntArrayList myQueuedChars;
private final TIntIntHashMap myLengthMap;
private int myOffset;
public EscapePreprocessor(Reader reader, int startOffset, TIntIntHashMap map) {
super(reader);
myOffset = startOffset;
myQueuedChars = new TIntArrayList();
myLengthMap = map;
}
@Override
public int read(char cbuf[], int off, int len) throws IOException {
final int i = read();
if (i == -1) {
return -1;
}
cbuf[off] = (char)i; // not really efficient, but acceptable since we're usually not having to deal with megabytes of RNC files...
return 1;
}
@Override
public int read() throws IOException {
if (myQueuedChars.size() > 0) {
return consume();
}
final int i = super.read();
if (i == -1) {
return -1;
}
myOffset++;
switch (i) {
case '\r':
assert false : "Unexpected newline character"; // IDEA document's are supposed to newlines normalized to \n
if (peek() == '\n') {
consume();
myLengthMap.put(myOffset - 1, 2);
}
case '\n':
return '\u0000';
case '\\':
int n = 0;
int x;
while ((x = peek()) == 'x') {
n++;
}
if (n > 0 && x == '{') {
n++;
} else {
return i;
}
int value = 0;
while (isHexChar((char)(x = peek()))) {
n++;
value <<= 4;
value |= Character.digit(x, 16);
}
if (x == '}') {
n++;
}
consume(n);
myLengthMap.put(myOffset - 1, n);
myOffset += n;
if (value <= 0xFFFF) {
return value;
}
myQueuedChars.add(Utf16.surrogate2(value));
return Utf16.surrogate1(value);
}
return i;
}
private static boolean isHexChar(char i) {
if (Character.isDigit(i)) return true;
final char c = Character.toLowerCase(i);
return c >= 'a' && c <= 'f';
}
private int consume() {
if (myQueuedChars.size() > 0) {
return myQueuedChars.remove(0);
}
return -1;
}
private void consume(int n) {
myQueuedChars.remove(0, n);
}
private int peek() throws IOException {
final int i = super.read();
if (i == -1) {
return -1;
}
myQueuedChars.add(i);
return i;
}
}
@@ -0,0 +1,420 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.
*/
/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 3.0 */
package org.intellij.plugins.relaxNG.compact.lexer;
import org.kohsuke.rngom.parse.compact.CharStream;
import org.kohsuke.rngom.parse.compact.EOFException;
/**
* An implementation of interface CharStream, where the stream is assumed to
* contain only ASCII characters (without unicode processing).
*/
@SuppressWarnings({ "ALL" })
public class SimpleCharStream implements CharStream
{
int bufsize;
int available;
int tokenBegin;
public int bufpos = -1;
protected int bufline[];
protected int bufcolumn[];
protected int column = 0;
protected int line = 1;
protected boolean prevCharIsCR = false;
protected boolean prevCharIsLF = false;
protected java.io.Reader inputStream;
protected char[] buffer;
protected int maxNextCharInd = 0;
protected int inBuf = 0;
protected void ExpandBuff(boolean wrapAround)
{
char[] newbuffer = new char[bufsize + 2048];
int newbufline[] = new int[bufsize + 2048];
int newbufcolumn[] = new int[bufsize + 2048];
try
{
if (wrapAround)
{
System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
System.arraycopy(buffer, 0, newbuffer,
bufsize - tokenBegin, bufpos);
buffer = newbuffer;
System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
bufline = newbufline;
System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
bufcolumn = newbufcolumn;
maxNextCharInd = (bufpos += (bufsize - tokenBegin));
}
else
{
System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
buffer = newbuffer;
System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
bufline = newbufline;
System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
bufcolumn = newbufcolumn;
maxNextCharInd = (bufpos -= tokenBegin);
}
}
catch (Throwable t)
{
throw new Error(t.getMessage());
}
bufsize += 2048;
available = bufsize;
tokenBegin = 0;
}
protected void FillBuff() throws EOFException
{
if (maxNextCharInd == available)
{
if (available == bufsize)
{
if (tokenBegin > 2048)
{
bufpos = maxNextCharInd = 0;
available = tokenBegin;
}
else if (tokenBegin < 0)
bufpos = maxNextCharInd = 0;
else
ExpandBuff(false);
}
else if (available > tokenBegin)
available = bufsize;
else if ((tokenBegin - available) < 2048)
ExpandBuff(true);
else
available = tokenBegin;
}
int i;
try {
if ((i = inputStream.read(buffer, maxNextCharInd,
available - maxNextCharInd)) == -1)
{
inputStream.close();
throw new java.io.IOException();
}
else
maxNextCharInd += i;
return;
}
catch(java.io.IOException e) {
--bufpos;
backup(0);
if (tokenBegin == -1)
tokenBegin = bufpos;
throw new EOFException();
}
}
public char BeginToken() throws EOFException
{
tokenBegin = -1;
char c = readChar();
tokenBegin = bufpos;
return c;
}
protected void UpdateLineColumn(char c)
{
column++;
if (prevCharIsLF)
{
prevCharIsLF = false;
line += (column = 1);
}
else if (prevCharIsCR)
{
prevCharIsCR = false;
if (c == '\n')
{
prevCharIsLF = true;
}
else
line += (column = 1);
}
switch (c)
{
case '\r' :
prevCharIsCR = true;
break;
case '\n' :
prevCharIsLF = true;
break;
case '\t' :
column--;
column += (8 - (column & 07));
break;
default :
break;
}
bufline[bufpos] = line;
bufcolumn[bufpos] = column;
}
public char readChar() throws EOFException
{
if (inBuf > 0)
{
--inBuf;
if (++bufpos == bufsize)
bufpos = 0;
return buffer[bufpos];
}
if (++bufpos >= maxNextCharInd)
FillBuff();
char c = buffer[bufpos];
UpdateLineColumn(c);
return (c);
}
/**
* @deprecated
* @see #getEndColumn
*/
public int getColumn() {
return bufcolumn[bufpos];
}
/**
* @deprecated
* @see #getEndLine
*/
public int getLine() {
return bufline[bufpos];
}
public int getEndColumn() {
return bufcolumn[bufpos];
}
public int getEndLine() {
return bufline[bufpos];
}
public int getBeginColumn() {
return bufcolumn[tokenBegin];
}
public int getBeginLine() {
return bufline[tokenBegin];
}
public void backup(int amount) {
inBuf += amount;
if ((bufpos -= amount) < 0)
bufpos += bufsize;
}
public SimpleCharStream(java.io.Reader dstream, int startline,
int startcolumn, int buffersize)
{
inputStream = dstream;
line = startline;
column = startcolumn - 1;
available = bufsize = buffersize;
buffer = new char[buffersize];
bufline = new int[buffersize];
bufcolumn = new int[buffersize];
}
public SimpleCharStream(java.io.Reader dstream, int startline,
int startcolumn)
{
this(dstream, startline, startcolumn, 4096);
}
public SimpleCharStream(java.io.Reader dstream)
{
this(dstream, 1, 1, 4096);
}
public void ReInit(java.io.Reader dstream, int startline,
int startcolumn, int buffersize)
{
inputStream = dstream;
line = startline;
column = startcolumn - 1;
if (buffer == null || buffersize != buffer.length)
{
available = bufsize = buffersize;
buffer = new char[buffersize];
bufline = new int[buffersize];
bufcolumn = new int[buffersize];
}
prevCharIsLF = prevCharIsCR = false;
tokenBegin = inBuf = maxNextCharInd = 0;
bufpos = -1;
}
public void ReInit(java.io.Reader dstream, int startline,
int startcolumn)
{
ReInit(dstream, startline, startcolumn, 4096);
}
public void ReInit(java.io.Reader dstream)
{
ReInit(dstream, 1, 1, 4096);
}
public SimpleCharStream(java.io.InputStream dstream, int startline,
int startcolumn, int buffersize)
{
this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
}
public SimpleCharStream(java.io.InputStream dstream, int startline,
int startcolumn)
{
this(dstream, startline, startcolumn, 4096);
}
public SimpleCharStream(java.io.InputStream dstream)
{
this(dstream, 1, 1, 4096);
}
public void ReInit(java.io.InputStream dstream, int startline,
int startcolumn, int buffersize)
{
ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
}
public void ReInit(java.io.InputStream dstream)
{
ReInit(dstream, 1, 1, 4096);
}
public void ReInit(java.io.InputStream dstream, int startline,
int startcolumn)
{
ReInit(dstream, startline, startcolumn, 4096);
}
public String GetImage()
{
if (bufpos >= tokenBegin)
return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
else
return new String(buffer, tokenBegin, bufsize - tokenBegin) +
new String(buffer, 0, bufpos + 1);
}
public char[] GetSuffix(int len)
{
char[] ret = new char[len];
if ((bufpos + 1) >= len)
System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
else
{
System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
len - bufpos - 1);
System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
}
return ret;
}
public void Done()
{
buffer = null;
bufline = null;
bufcolumn = null;
}
/**
* Method to adjust line and column numbers for the start of a token.
*/
public void adjustBeginLineColumn(int newLine, int newCol)
{
int start = tokenBegin;
int len;
if (bufpos >= tokenBegin)
{
len = bufpos - tokenBegin + inBuf + 1;
}
else
{
len = bufsize - tokenBegin + bufpos + 1 + inBuf;
}
int i = 0, j = 0, k = 0;
int nextColDiff = 0, columnDiff = 0;
while (i < len &&
bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
{
bufline[j] = newLine;
nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
bufcolumn[j] = newCol + columnDiff;
columnDiff = nextColDiff;
i++;
}
if (i < len)
{
bufline[j] = newLine++;
bufcolumn[j] = newCol + columnDiff;
while (i++ < len)
{
if (bufline[j = start % bufsize] != bufline[++start % bufsize])
bufline[j] = newLine++;
else
bufline[j] = newLine;
}
}
line = bufline[j];
column = bufcolumn[j];
}
}
@@ -0,0 +1,156 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact.parser;
import org.intellij.plugins.relaxNG.compact.RncElementTypes;
import static org.intellij.plugins.relaxNG.compact.RncTokenTypes.*;
import com.intellij.lang.PsiBuilder;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 09.08.2007
*/
public abstract class AbstractParsing {
protected static final TokenSet LA_INCLUDE_CONTENT = TokenSet.orSet(TokenSet.create(
KEYWORD_DIV, KEYWORD_START), IDENTIFIERS);
protected static final TokenSet LA_GRAMMAR_CONTENT = TokenSet.orSet(TokenSet.create(
KEYWORD_INCLUDE), LA_INCLUDE_CONTENT);
protected static final TokenSet ATTR_OR_ELEMENT = TokenSet.create(
KEYWORD_ATTRIBUTE, KEYWORD_ElEMENT);
protected static final TokenSet CONTENT = TokenSet.create(
KEYWORD_LIST, KEYWORD_MIXED);
protected static final TokenSet LA_DATATYPE = TokenSet.create(
KEYWORD_STRING, KEYWORD_TOKEN);
protected static final TokenSet LA_DECL = TokenSet.create(
KEYWORD_DATATYPES, KEYWORD_NAMESPACE, KEYWORD_DEFAULT);
protected static final TokenSet NS_URI_LITERAL = TokenSet.create(KEYWORD_INHERIT, LITERAL);
protected static final TokenSet ASSIGN_METHOD = TokenSet.create(EQ, CHOICE_EQ, INTERLEAVE_EQ);
protected final PsiBuilder myBuilder;
public AbstractParsing(PsiBuilder builder) {
myBuilder = builder;
}
protected final PsiBuilder.Marker begin() {
final PsiBuilder.Marker marker = myBuilder.mark();
advance();
return marker;
}
protected final boolean matches(TokenSet set) {
if (set.contains(currentToken())) {
advance();
return true;
}
return false;
}
protected final boolean matches(IElementType t) {
if (t == currentToken()) {
advance();
return true;
}
return false;
}
protected final void match(IElementType token, String msg) {
if (!matches(token)) {
error(msg);
advance();
}
}
protected final void match(TokenSet set, String msg) {
if (!matches(set)) {
error(msg);
advance();
}
}
protected final void error(String s) {
myBuilder.error(s);
}
protected final void advance() {
myBuilder.advanceLexer();
}
protected final IElementType currentToken() {
final IElementType token = myBuilder.getTokenType();
if (isName(token)) {
final PsiBuilder.Marker marker = myBuilder.mark();
makeName();
if (myBuilder.getTokenType() == LBRACKET) {
skipAnnotation(marker, RncElementTypes.ANNOTATION_ELEMENT);
return currentToken();
} else {
marker.rollbackTo();
}
} else if (token == LBRACKET) {
final PsiBuilder.Marker marker = myBuilder.mark();
skipAnnotation(marker, RncElementTypes.ANNOTATION);
return currentToken();
} else if (token == GTGT) {
final PsiBuilder.Marker marker = myBuilder.mark();
advance();
if (isName(myBuilder.getTokenType())) {
makeName();
if (myBuilder.getTokenType() == LBRACKET) {
skipAnnotation(marker, RncElementTypes.FORWARD_ANNOTATION);
return currentToken();
}
}
marker.done(RncElementTypes.FORWARD_ANNOTATION);
return currentToken();
}
return token;
}
protected static boolean isName(IElementType token) {
return IDENTIFIER_OR_KEYWORD.contains(token) || token == PREFIXED_NAME;
}
private void skipAnnotation(PsiBuilder.Marker marker, IElementType annotationType) {
final boolean b = myBuilder.getTokenType() == LBRACKET;
advance();
assert b;
while (!myBuilder.eof() && currentToken() != RBRACKET) {
advance();
}
if (myBuilder.getTokenType() == RBRACKET) {
advance();
}
marker.done(annotationType);
}
protected final void makeName() {
final PsiBuilder.Marker name = myBuilder.mark();
advance();
name.done(RncElementTypes.NAME);
}
}
@@ -0,0 +1,178 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact.parser;
import org.intellij.plugins.relaxNG.compact.RncElementTypes;
import static org.intellij.plugins.relaxNG.compact.RncTokenTypes.*;
import com.intellij.lang.PsiBuilder;
import com.intellij.psi.tree.IElementType;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 09.08.2007
*/
public abstract class DeclarationParsing extends AbstractParsing {
public DeclarationParsing(PsiBuilder builder) {
super(builder);
}
protected void parseTopLevel() {
while (!myBuilder.eof() && LA_DECL.contains(currentToken())) {
parseDecl(myBuilder);
}
if (LA_GRAMMAR_CONTENT.contains(currentToken())) {
final PsiBuilder.Marker marker = myBuilder.mark();
parseGrammarContents();
marker.done(RncElementTypes.GRAMMAR_PATTERN);
} else if (currentToken() == KEYWORD_GRAMMAR) {
parsePattern();
} else {
final PsiBuilder.Marker marker = myBuilder.mark();
while (!myBuilder.eof()) {
if (!parsePattern()) {
break;
}
}
marker.done(RncElementTypes.GRAMMAR_PATTERN);
}
}
protected abstract boolean parsePattern();
protected void parseGrammarContents() {
while (LA_GRAMMAR_CONTENT.contains(currentToken())) {
parseGrammarContent(true);
}
}
private void parseIncludeContents() {
while (LA_INCLUDE_CONTENT.contains(currentToken())) {
parseGrammarContent(false);
}
}
private void parseGrammarContent(boolean allowInclude) {
final IElementType t = currentToken();
if (t == KEYWORD_START) {
parseStart();
} else if (t == KEYWORD_DIV) {
parseDiv();
} else if (allowInclude && t == KEYWORD_INCLUDE) {
parseInclude();
} else if (IDENTIFIERS.contains(t)) {
parseDefine();
} else {
error("Unexpected token");
advance();
}
}
private void parseDefine() {
final PsiBuilder.Marker marker = begin();
match(ASSIGN_METHOD, "'=', '|=' or '&=' expected");
if (!parsePattern()) {
error("Pattern expected");
}
marker.done(RncElementTypes.DEFINE);
}
private void parseInclude() {
final PsiBuilder.Marker marker = begin();
parseAnyUriLiteral();
parseInherit();
if (matches(LBRACE)) {
parseIncludeContents();
match(RBRACE, "'}' expected");
}
marker.done(RncElementTypes.INCLUDE);
}
protected final void parseAnyUriLiteral() {
match(LITERAL, "URI literal expected");
}
protected final void parseInherit() {
if (matches(KEYWORD_INHERIT)) {
match(EQ, "'=' expected");
match(IDENTIFIER_OR_KEYWORD, "Identifier expected");
}
}
private void parseDiv() {
final PsiBuilder.Marker marker = begin();
parseBracedGrammarContents();
marker.done(RncElementTypes.DIV);
}
private void parseStart() {
final PsiBuilder.Marker marker = begin();
match(ASSIGN_METHOD, "'=', '|=' or '&=' expected");
if (!parsePattern()) {
error("Pattern expected");
}
marker.done(RncElementTypes.START);
}
protected void parseBracedGrammarContents() {
match(LBRACE, "'{' expected");
parseGrammarContents();
match(RBRACE, "'}' expected");
}
protected void parseDecl(PsiBuilder builder) {
final IElementType t = builder.getTokenType();
if (t == KEYWORD_NAMESPACE) {
parseNamespaceDecl(false);
} else if (t == KEYWORD_DEFAULT) {
parseNamespaceDecl(true);
} else if (t == KEYWORD_DATATYPES) {
parseDataTypesDecl();
}
}
private void parseDataTypesDecl() {
final PsiBuilder.Marker marker = begin();
match(IDENTIFIER_OR_KEYWORD, "Identifier expected");
match(EQ, "'=' expected");
parseNsUriLiteral();
marker.done(RncElementTypes.DATATYPES_DECL);
}
private void parseNamespaceDecl(boolean isDefault) {
final PsiBuilder.Marker marker = begin();
if (isDefault) {
match(KEYWORD_NAMESPACE, "'namespace' expected");
matches(IDENTIFIER_OR_KEYWORD);
} else {
match(IDENTIFIER_OR_KEYWORD, "Identifier expected");
}
match(EQ, "'=' expected");
parseNsUriLiteral();
marker.done(RncElementTypes.NS_DECL);
}
private void parseNsUriLiteral() {
match(NS_URI_LITERAL, "Namespace URI or 'inherit' expected");
}
}
@@ -0,0 +1,88 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact.parser;
import org.intellij.plugins.relaxNG.compact.RncElementTypes;
import static org.intellij.plugins.relaxNG.compact.RncTokenTypes.*;
import com.intellij.lang.PsiBuilder;
import com.intellij.psi.tree.IElementType;
public class NameClassParsing extends AbstractParsing {
public NameClassParsing(PsiBuilder builder) {
super(builder);
}
public boolean parseNameClass() {
PsiBuilder.Marker marker = myBuilder.mark();
if (!parseNameClassPart()) {
marker.drop();
return false;
}
if (currentToken() == PIPE) {
do {
advance();
if (!parseNameClassPart()) {
error("NameClass expected");
}
} while (currentToken() == PIPE);
marker.done(RncElementTypes.NAME_CLASS_CHOICE);
} else {
marker.drop();
}
return true;
}
private boolean parseNameClassPart() {
final IElementType t = currentToken();
PsiBuilder.Marker marker = myBuilder.mark();
if (IDENTIFIER_OR_KEYWORD.contains(t)) {
advance();
} else if (PREFIXED_NAME == t) { // CName
makeName();
} else if (STAR == t) { // anyName
advance();
parseExceptNameClass();
} else if (PREFIXED_STAR == t) { // nsName
makeName();
parseExceptNameClass();
} else if (LPAREN == t) {
advance();
if (parseNameClass()) {
match(RPAREN, "')' expected");
}
} else {
marker.drop();
return false;
}
marker.done(RncElementTypes.NAME_CLASS);
return true;
}
private void parseExceptNameClass() {
if (MINUS == currentToken()) {
final PsiBuilder.Marker marker = begin();
if (!parseNameClass()) {
error("NameClass expected");
}
marker.done(RncElementTypes.EXCEPT_NAME_CLASS);
}
}
}
@@ -0,0 +1,191 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact.parser;
import org.intellij.plugins.relaxNG.compact.RncElementTypes;
import static org.intellij.plugins.relaxNG.compact.RncTokenTypes.*;
import com.intellij.lang.PsiBuilder;
import com.intellij.psi.tree.IElementType;
import gnu.trove.THashMap;
import gnu.trove.TObjectHashingStrategy;
import java.util.Map;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 09.08.2007
*/
public class PatternParsing extends DeclarationParsing {
@SuppressWarnings({ "unchecked" })
protected static final Map<IElementType, IElementType> TOKEN_MAP =
new THashMap<IElementType, IElementType>(TObjectHashingStrategy.IDENTITY);
static {
TOKEN_MAP.put(COMMA, RncElementTypes.SEQUENCE);
TOKEN_MAP.put(PIPE, RncElementTypes.CHOICE);
TOKEN_MAP.put(AND, RncElementTypes.INTERLEAVE);
TOKEN_MAP.put(STAR, RncElementTypes.ZERO_OR_MORE);
TOKEN_MAP.put(PLUS, RncElementTypes.ONE_OR_MORE);
TOKEN_MAP.put(QUEST, RncElementTypes.OPTIONAL);
}
private final NameClassParsing myNameClassParsing;
public PatternParsing(PsiBuilder builder) {
super(builder);
myNameClassParsing = new NameClassParsing(builder);
}
public void parse() {
parseTopLevel();
}
protected boolean parsePattern() {
PsiBuilder.Marker marker = myBuilder.mark();
if (!parseQuantifiedPattern()) {
marker.drop();
return false;
}
while (BINARY_OPS.contains(currentToken())) {
IElementType t;
if (BINARY_OPS.contains(t = currentToken())) {
do {
advance();
if (!parseQuantifiedPattern()) {
error("Pattern expected");
}
} while (currentToken() == t);
marker.done(TOKEN_MAP.get(t));
marker = marker.precede();
}
}
marker.drop();
return true;
}
private boolean parseQuantifiedPattern() {
final PsiBuilder.Marker marker = myBuilder.mark();
if (!parseSinglePattern()) {
marker.drop();
return false;
}
final IElementType t = currentToken();
if (matches(QUANTIFIER_OPS)) {
marker.done(TOKEN_MAP.get(t));
} else {
marker.drop();
}
return true;
}
private boolean parseSinglePattern() {
final PsiBuilder.Marker marker = myBuilder.mark();
if (matches(ATTR_OR_ELEMENT)) {
if (!myNameClassParsing.parseNameClass()) {
error("Name class expected");
marker.drop();
return false;
}
parseBracedPattern();
marker.done(RncElementTypes.PATTERN);
} else if (matches(KEYWORD_LIST)) {
parseBracedPattern();
marker.done(RncElementTypes.LIST_PATTERN);
} else if (matches(KEYWORD_MIXED)) {
parseBracedPattern();
marker.done(RncElementTypes.MIXED_PATTERN);
} else if (matches(KEYWORD_EXTERNAL)) {
parseAnyUriLiteral();
parseInherit();
marker.done(RncElementTypes.EXTERNAL_REF);
} else if (matches(KEYWORD_NOT_ALLOWED)) {
marker.done(RncElementTypes.NOT_ALLOWED_PATTERN);
} else if (matches(KEYWORD_TEXT)) {
marker.done(RncElementTypes.TEXT_PATTERN);
} else if (matches(KEYWORD_EMPTY)) {
marker.done(RncElementTypes.EMPTY_PATTERN);
} else if (matches(KEYWORD_PARENT)) {
match(IDENTIFIERS, "Identifier expected");
marker.done(RncElementTypes.PARENT_REF);
} else if (matches(KEYWORD_GRAMMAR)) {
parseBracedGrammarContents();
marker.done(RncElementTypes.GRAMMAR_PATTERN);
} else if (matches(LPAREN)) {
if (!parsePattern()) {
error("Pattern expected");
}
match(RPAREN, "')' expected");
marker.done(RncElementTypes.GROUP_PATTERN);
} else if (matches(IDENTIFIERS)) {
marker.done(RncElementTypes.REF_PATTERN);
} else if (matches(LA_DATATYPE)) {
parseDatatype();
marker.done(RncElementTypes.DATATYPE_PATTERN);
} else if (currentToken() == PREFIXED_NAME) {
makeName();
parseDatatype();
marker.done(RncElementTypes.DATATYPE_PATTERN);
} else if (matches(LITERAL)) {
marker.done(RncElementTypes.DATATYPE_PATTERN);
} else {
marker.drop();
return false;
}
return true;
}
private void parseDatatype() {
if (currentToken() == LITERAL) {
advance();
} else if (matches(LBRACE)) {
parseParams();
if (matches(MINUS)) {
if (!parsePattern()) {
error("Pattern expected");
}
}
match(RBRACE, "'}' expected");
}
}
private void parseBracedPattern() {
match(LBRACE, "'{' expected");
if (!parsePattern()) {
error("Pattern expected");
}
match(RBRACE, "'}' expected");
}
private void parseParams() {
final IElementType t = currentToken();
if (t != RBRACE) {
do {
final PsiBuilder.Marker marker = myBuilder.mark();
match(IDENTIFIER_OR_KEYWORD, "Identifier expected");
match(EQ, "'=' expected");
match(LITERAL, "Literal expected");
marker.done(RncElementTypes.PARAM);
} while (IDENTIFIER_OR_KEYWORD.contains(currentToken()));
}
}
}
@@ -0,0 +1,50 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact.parser;
import org.intellij.plugins.relaxNG.compact.RncElementTypes;
import com.intellij.lang.ASTNode;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.PsiParser;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 07.08.2007
*/
public class RncParser implements PsiParser {
@NotNull
public ASTNode parse(IElementType root, PsiBuilder builder) {
final PsiBuilder.Marker fileMarker = builder.mark();
final PsiBuilder.Marker docMarker = builder.mark();
new PatternParsing(builder).parse();
while (!builder.eof()) {
builder.error("Unexpected token");
builder.advanceLexer();
}
docMarker.done(RncElementTypes.DOCUMENT);
fileMarker.done(root);
return builder.getTreeBuilt();
}
}
@@ -0,0 +1,30 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact.psi;
import com.intellij.psi.PsiComment;
import org.jetbrains.annotations.Nullable;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 24.08.2007
*/
public interface RncAnnotation extends RncElement, PsiComment {
@Nullable
RncName getNameElement();
}
@@ -0,0 +1,30 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact.psi;
import com.intellij.psi.PsiNamedElement;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 16.08.2007
*/
public interface RncDecl extends RncElement, PsiNamedElement {
String getPrefix();
String getDeclaredNamespace();
}
@@ -0,0 +1,32 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact.psi;
import org.intellij.plugins.relaxNG.model.Define;
import com.intellij.psi.PsiNamedElement;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 13.08.2007
*/
public interface RncDefine extends RncPattern, PsiNamedElement, Define<RncPattern, RncElement> {
@Nullable
RncPattern getPattern();
}
@@ -0,0 +1,27 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact.psi;
import org.intellij.plugins.relaxNG.model.Div;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 24.08.2007
*/
public interface RncDiv extends RncElement, Div<RncElement> {
}
@@ -0,0 +1,27 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact.psi;
import com.intellij.psi.PsiElement;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 10.08.2007
*/
public interface RncElement extends PsiElement {
}
@@ -0,0 +1,76 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact.psi;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
public class RncElementVisitor extends PsiElementVisitor {
@Override
public final void visitElement(PsiElement element) {
if (element instanceof RncElement) {
visitElement((RncElement)element);
} else {
superVisitElement(element);
}
}
protected void superVisitElement(PsiElement element) {
super.visitElement(element);
}
public void visitElement(RncElement element) {
super.visitElement(element);
}
public void visitInclude(RncInclude include) {
visitElement(include);
}
public void visitDiv(RncDiv div) {
visitElement(div);
}
public void visitRef(RncRef pattern) {
visitElement(pattern);
}
public void visitParentRef(RncParentRef pattern) {
visitElement(pattern);
}
public void visitDefine(RncDefine pattern) {
visitElement(pattern);
}
public void visitGrammar(RncGrammar pattern) {
visitElement(pattern);
}
public void visitName(RncName name) {
visitElement(name);
}
public void visitAnnotation(RncAnnotation annotation) {
visitElement(annotation);
}
public void visitExternalRef(RncExternalRef ref) {
visitElement(ref);
}
}
@@ -0,0 +1,26 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact.psi;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 11.08.2007
*/
public interface RncExternalRef extends RncFileReference {
}
@@ -0,0 +1,32 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact.psi;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 11.08.2007
*/
public interface RncFile extends PsiFile {
RncDecl[] getDeclarations();
@Nullable
RncGrammar getGrammar();
}
@@ -0,0 +1,35 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact.psi;
import com.intellij.openapi.util.TextRange;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 29.08.2007
*/
public interface RncFileReference extends RncElement {
@Nullable
RncFile getReferencedFile();
@Nullable
String getFileReference();
TextRange getReferenceRange();
}
@@ -0,0 +1,31 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.plugins.relaxNG.compact.psi;
import org.intellij.plugins.relaxNG.model.Grammar;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 13.08.2007
*/
public interface RncGrammar extends RncElement, Grammar<RncPattern, RncElement> {
@Nullable
RncPattern getStart();
}

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