mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git.labs.intellij.net:idea/community
This commit is contained in:
Generated
+1
@@ -4,6 +4,7 @@
|
||||
<scope name="IDEA Test Sources" pattern="test:*..*" />
|
||||
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
|
||||
</component>
|
||||
<component name="IdProvider" IDEtalkID="88DB5D232B345F18EEFB2825E88EC093" />
|
||||
<component name="JavadocGenerationManager">
|
||||
<option name="OUTPUT_DIRECTORY" />
|
||||
<option name="OPTION_SCOPE" value="protected" />
|
||||
|
||||
Generated
+10
-10
@@ -127,6 +127,16 @@
|
||||
<option name="LABEL_INDENT_ABSOLUTE" value="false" />
|
||||
<option name="USE_RELATIVE_INDENTS" value="false" />
|
||||
</ADDITIONAL_INDENT_OPTIONS>
|
||||
<ADDITIONAL_INDENT_OPTIONS fileType="html">
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
<option name="TAB_SIZE" value="8" />
|
||||
<option name="USE_TAB_CHARACTER" value="false" />
|
||||
<option name="SMART_TABS" value="false" />
|
||||
<option name="LABEL_INDENT_SIZE" value="0" />
|
||||
<option name="LABEL_INDENT_ABSOLUTE" value="false" />
|
||||
<option name="USE_RELATIVE_INDENTS" value="false" />
|
||||
</ADDITIONAL_INDENT_OPTIONS>
|
||||
<ADDITIONAL_INDENT_OPTIONS fileType="java">
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||
@@ -147,16 +157,6 @@
|
||||
<option name="LABEL_INDENT_ABSOLUTE" value="false" />
|
||||
<option name="USE_RELATIVE_INDENTS" value="false" />
|
||||
</ADDITIONAL_INDENT_OPTIONS>
|
||||
<ADDITIONAL_INDENT_OPTIONS fileType="jsp">
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
<option name="TAB_SIZE" value="8" />
|
||||
<option name="USE_TAB_CHARACTER" value="false" />
|
||||
<option name="SMART_TABS" value="false" />
|
||||
<option name="LABEL_INDENT_SIZE" value="0" />
|
||||
<option name="LABEL_INDENT_ABSOLUTE" value="false" />
|
||||
<option name="USE_RELATIVE_INDENTS" value="false" />
|
||||
</ADDITIONAL_INDENT_OPTIONS>
|
||||
<ADDITIONAL_INDENT_OPTIONS fileType="rb">
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="8" />
|
||||
|
||||
+9
-2
@@ -43,11 +43,18 @@ public class ArchiveAntCopyInstructionCreator implements AntCopyInstructionCreat
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public AntCopyInstructionCreator subFolder(String directoryName) {
|
||||
public AntCopyInstructionCreator subFolder(@NotNull String directoryName) {
|
||||
return new ArchiveAntCopyInstructionCreator(myPrefix + "/" + directoryName);
|
||||
}
|
||||
|
||||
public Generator createSubFolderCommand(String directoryName) {
|
||||
public Generator createSubFolderCommand(@NotNull String directoryName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Generator createExtractedDirectoryInstruction(@NotNull String jarPath, @NotNull String pathInJar) {
|
||||
final String pattern = pathInJar.length() == 0 ? null : pathInJar + "**";
|
||||
return ZipFileSet.createUnpackedSet(jarPath, pathInJar, true, pattern);
|
||||
}
|
||||
}
|
||||
|
||||
+15
-5
@@ -17,9 +17,7 @@ package com.intellij.compiler.ant.artifacts;
|
||||
|
||||
import com.intellij.compiler.ant.Generator;
|
||||
import com.intellij.compiler.ant.Tag;
|
||||
import com.intellij.compiler.ant.taskdefs.Copy;
|
||||
import com.intellij.compiler.ant.taskdefs.FileSet;
|
||||
import com.intellij.compiler.ant.taskdefs.Mkdir;
|
||||
import com.intellij.compiler.ant.taskdefs.*;
|
||||
import com.intellij.packaging.elements.AntCopyInstructionCreator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -50,11 +48,23 @@ public class DirectoryAntCopyInstructionCreator implements AntCopyInstructionCre
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public AntCopyInstructionCreator subFolder(String directoryName) {
|
||||
public AntCopyInstructionCreator subFolder(@NotNull String directoryName) {
|
||||
return new DirectoryAntCopyInstructionCreator(myOutputDirectory + "/" + directoryName);
|
||||
}
|
||||
|
||||
public Generator createSubFolderCommand(String directoryName) {
|
||||
public Generator createSubFolderCommand(@NotNull String directoryName) {
|
||||
return new Mkdir(myOutputDirectory + "/" + directoryName);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Generator createExtractedDirectoryInstruction(@NotNull String jarPath, @NotNull String pathInJar) {
|
||||
final Unzip unzip = new Unzip(jarPath, myOutputDirectory);
|
||||
if (pathInJar.length() > 0) {
|
||||
final PatternSet patterns = new PatternSet(null);
|
||||
patterns.add(new Include(pathInJar + "**"));
|
||||
unzip.add(patterns);
|
||||
}
|
||||
return unzip;
|
||||
}
|
||||
}
|
||||
|
||||
+37
-6
@@ -25,6 +25,7 @@ import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.packaging.impl.compiler.ArtifactCompilerUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.graph.CachingSemiGraph;
|
||||
import com.intellij.util.graph.DFSTBuilder;
|
||||
@@ -159,8 +160,14 @@ public class JarsBuilder {
|
||||
try {
|
||||
final THashSet<String> writtenPaths = new THashSet<String>();
|
||||
for (Pair<String, VirtualFile> pair : jar.getPackedFiles()) {
|
||||
File file = VfsUtil.virtualToIoFile(pair.getSecond());
|
||||
addFileToJar(jarOutputStream, file, pair.getFirst(), writtenPaths);
|
||||
final VirtualFile sourceFile = pair.getSecond();
|
||||
if (sourceFile.isInLocalFileSystem()) {
|
||||
File file = VfsUtil.virtualToIoFile(sourceFile);
|
||||
addFileToJar(jarOutputStream, file, pair.getFirst(), writtenPaths);
|
||||
}
|
||||
else {
|
||||
extractFileAndAddToJar(jarOutputStream, sourceFile, pair.getFirst(), writtenPaths);
|
||||
}
|
||||
}
|
||||
|
||||
for (Pair<String, JarInfo> nestedJar : jar.getPackedJars()) {
|
||||
@@ -178,9 +185,35 @@ public class JarsBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
private void extractFileAndAddToJar(JarOutputStream jarOutputStream, VirtualFile sourceFile, String relativePath, THashSet<String> writtenPaths)
|
||||
throws IOException {
|
||||
relativePath = addParentDirectories(jarOutputStream, writtenPaths, relativePath);
|
||||
myContext.getProgressIndicator().setText2(relativePath);
|
||||
if (!writtenPaths.add(relativePath)) return;
|
||||
|
||||
final BufferedInputStream input = ArtifactCompilerUtil.getJarEntryInputStream(sourceFile, myContext);
|
||||
if (input == null) return;
|
||||
|
||||
ZipEntry entry = new ZipEntry(relativePath);
|
||||
entry.setTime(ArtifactCompilerUtil.getJarFile(sourceFile).lastModified());
|
||||
jarOutputStream.putNextEntry(entry);
|
||||
FileUtil.copy(input, jarOutputStream);
|
||||
jarOutputStream.closeEntry();
|
||||
}
|
||||
|
||||
private void addFileToJar(final @NotNull JarOutputStream jarOutputStream, final @NotNull File file, @NotNull String relativePath,
|
||||
final @NotNull THashSet<String> writtenPaths) throws IOException {
|
||||
//todo[nik] check file exists?
|
||||
if (!file.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
relativePath = addParentDirectories(jarOutputStream, writtenPaths, relativePath);
|
||||
myContext.getProgressIndicator().setText2(relativePath);
|
||||
ZipUtil.addFileToZip(jarOutputStream, file, relativePath, writtenPaths, myFileFilter);
|
||||
}
|
||||
|
||||
private static String addParentDirectories(JarOutputStream jarOutputStream, THashSet<String> writtenPaths, String relativePath)
|
||||
throws IOException {
|
||||
while (relativePath.startsWith("/")) {
|
||||
relativePath = relativePath.substring(1);
|
||||
}
|
||||
@@ -193,9 +226,7 @@ public class JarsBuilder {
|
||||
}
|
||||
i = relativePath.indexOf('/', i + 1);
|
||||
}
|
||||
|
||||
myContext.getProgressIndicator().setText2(relativePath);
|
||||
ZipUtil.addFileToZip(jarOutputStream, file, relativePath, writtenPaths, myFileFilter);
|
||||
return relativePath;
|
||||
}
|
||||
|
||||
private static void addEntry(final ZipOutputStream output, @NonNls final String relativePath) throws IOException {
|
||||
|
||||
@@ -320,6 +320,7 @@ public class ArtifactUtil {
|
||||
boolean processSubstitutions) {
|
||||
processPackagingElements(artifact, PackagingElementFactoryImpl.FILE_COPY_ELEMENT_TYPE, processor, context, processSubstitutions);
|
||||
processPackagingElements(artifact, PackagingElementFactoryImpl.DIRECTORY_COPY_ELEMENT_TYPE, processor, context, processSubstitutions);
|
||||
processPackagingElements(artifact, PackagingElementFactoryImpl.EXTRACTED_DIRECTORY_ELEMENT_TYPE, processor, context, processSubstitutions);
|
||||
}
|
||||
|
||||
public static Collection<Trinity<Artifact, PackagingElementPath, String>> findContainingArtifactsWithOutputPaths(@NotNull final VirtualFile file, @NotNull Project project) {
|
||||
@@ -417,8 +418,8 @@ public class ArtifactUtil {
|
||||
ContainerUtil.addIfNotNull(fileCopyElement.findFile(), result);
|
||||
}
|
||||
}
|
||||
else if (element instanceof DirectoryCopyPackagingElement) {
|
||||
final VirtualFile sourceRoot = ((DirectoryCopyPackagingElement)element).findFile();
|
||||
else if (element instanceof DirectoryCopyPackagingElement || element instanceof ExtractedDirectoryPackagingElement) {
|
||||
final VirtualFile sourceRoot = ((FileOrDirectoryCopyPackagingElement<?>)element).findFile();
|
||||
if (sourceRoot != null) {
|
||||
ContainerUtil.addIfNotNull(sourceRoot.findFileByRelativePath(path), result);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.packaging.impl.compiler;
|
||||
|
||||
import com.intellij.openapi.compiler.CompileContext;
|
||||
import com.intellij.openapi.compiler.CompilerMessageCategory;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.JarFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ArtifactCompilerUtil {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.packaging.impl.compiler.ArtifactCompilerUtil");
|
||||
|
||||
private ArtifactCompilerUtil() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static BufferedInputStream getJarEntryInputStream(VirtualFile sourceFile, final CompileContext context) throws IOException {
|
||||
final String fullPath = sourceFile.getPath();
|
||||
final int jarEnd = fullPath.indexOf(JarFileSystem.JAR_SEPARATOR);
|
||||
LOG.assertTrue(jarEnd != -1, fullPath);
|
||||
String pathInJar = fullPath.substring(jarEnd + JarFileSystem.JAR_SEPARATOR.length());
|
||||
String jarPath = fullPath.substring(0, jarEnd);
|
||||
final ZipFile jarFile = new ZipFile(new File(FileUtil.toSystemDependentName(jarPath)));
|
||||
final ZipEntry entry = jarFile.getEntry(pathInJar);
|
||||
if (entry == null) {
|
||||
context.addMessage(CompilerMessageCategory.ERROR, "Cannot extract '" + pathInJar + "' from '" + jarFile.getName() + "': entry not found", null, -1, -1);
|
||||
return null;
|
||||
}
|
||||
|
||||
return new BufferedInputStream(jarFile.getInputStream(entry)) {
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
super.close();
|
||||
jarFile.close();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static File getJarFile(VirtualFile jarEntry) {
|
||||
String fullPath = jarEntry.getPath();
|
||||
return new File(FileUtil.toSystemDependentName(fullPath.substring(fullPath.indexOf(JarFileSystem.JAR_SEPARATOR))));
|
||||
}
|
||||
}
|
||||
+38
-12
@@ -31,7 +31,7 @@ import com.intellij.openapi.deployment.DeploymentUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
@@ -53,9 +53,7 @@ import com.intellij.util.text.CaseInsensitiveStringHashingStrategy;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@@ -164,7 +162,7 @@ public class ArtifactsCompilerInstance extends CompilerInstance<ArtifactBuildTar
|
||||
|
||||
private boolean doBuild(final List<Pair<ArtifactCompilerCompileItem, ArtifactPackagingItemOutputState>> changedItems,
|
||||
final Set<ArtifactCompilerCompileItem> processedItems,
|
||||
final Set<String> writtenPaths, final Set<String> deletedJars) {
|
||||
final @NotNull Set<String> writtenPaths, final Set<String> deletedJars) {
|
||||
final boolean testMode = ApplicationManager.getApplication().isUnitTestMode();
|
||||
|
||||
final DeploymentUtil deploymentUtil = DeploymentUtil.getInstance();
|
||||
@@ -188,20 +186,26 @@ public class ArtifactsCompilerInstance extends CompilerInstance<ArtifactBuildTar
|
||||
final Ref<IOException> exception = Ref.create(null);
|
||||
new ReadAction() {
|
||||
protected void run(final Result result) {
|
||||
final File fromFile = VfsUtil.virtualToIoFile(sourceItem.getFile());
|
||||
final VirtualFile sourceFile = sourceItem.getFile();
|
||||
for (DestinationInfo destination : sourceItem.getDestinations()) {
|
||||
if (destination instanceof ExplodedDestinationInfo) {
|
||||
final ExplodedDestinationInfo explodedDestination = (ExplodedDestinationInfo)destination;
|
||||
File toFile = new File(FileUtil.toSystemDependentName(explodedDestination.getOutputPath()));
|
||||
if (fromFile.exists()) {
|
||||
try {
|
||||
deploymentUtil.copyFile(fromFile, toFile, myContext, writtenPaths, fileFilter);
|
||||
try {
|
||||
if (sourceFile.isInLocalFileSystem()) {
|
||||
final File ioFromFile = VfsUtil.virtualToIoFile(sourceFile);
|
||||
if (ioFromFile.exists()) {
|
||||
deploymentUtil.copyFile(ioFromFile, toFile, myContext, writtenPaths, fileFilter);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
exception.set(e);
|
||||
return;
|
||||
else {
|
||||
extractFile(sourceFile, toFile, writtenPaths, fileFilter);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
exception.set(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
changedJars.add(((JarDestinationInfo)destination).getJarInfo());
|
||||
@@ -254,6 +258,28 @@ public class ArtifactsCompilerInstance extends CompilerInstance<ArtifactBuildTar
|
||||
return true;
|
||||
}
|
||||
|
||||
private void extractFile(VirtualFile sourceFile, File toFile, Set<String> writtenPaths, FileFilter fileFilter) throws IOException {
|
||||
if (!writtenPaths.add(toFile.getPath())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!FileUtil.createParentDirs(toFile)) {
|
||||
myContext.addMessage(CompilerMessageCategory.ERROR, "Cannot create directory for '" + toFile.getAbsolutePath() + "' file", null, -1, -1);
|
||||
return;
|
||||
}
|
||||
|
||||
final BufferedInputStream input = ArtifactCompilerUtil.getJarEntryInputStream(sourceFile, myContext);
|
||||
if (input == null) return;
|
||||
final BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(toFile));
|
||||
try {
|
||||
FileUtil.copy(input, output);
|
||||
}
|
||||
finally {
|
||||
input.close();
|
||||
output.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void onBuildStartedOrFinished(final boolean finished) throws Exception {
|
||||
final Set<Artifact> artifacts = myContext.getUserData(ArtifactsCompiler.AFFECTED_ARTIFACTS);
|
||||
if (artifacts != null) {
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ public class DirectoryCopyPackagingElement extends FileOrDirectoryCopyPackagingE
|
||||
@NotNull ArtifactAntGenerationContext generationContext,
|
||||
@NotNull ArtifactType artifactType) {
|
||||
final String path = generationContext.getSubstitutedPath(myFilePath);
|
||||
return Collections.singletonList((Generator)creator.createDirectoryContentCopyInstruction(path));
|
||||
return Collections.singletonList(creator.createDirectoryContentCopyInstruction(path));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.packaging.impl.elements;
|
||||
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDialog;
|
||||
import com.intellij.openapi.fileChooser.FileChooserFactory;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.vfs.JarFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.packaging.artifacts.Artifact;
|
||||
import com.intellij.packaging.elements.CompositePackagingElement;
|
||||
import com.intellij.packaging.elements.PackagingElementType;
|
||||
import com.intellij.packaging.ui.ArtifactEditorContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ExtractedDirectoryElementType extends PackagingElementType<ExtractedDirectoryPackagingElement> {
|
||||
public static final Icon EXTRACTED_FOLDER_ICON = IconLoader.getIcon("/nodes/extractedFolder.png");
|
||||
|
||||
ExtractedDirectoryElementType() {
|
||||
super("extracted-dir", "Extracted Directory");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getCreateElementIcon() {
|
||||
return EXTRACTED_FOLDER_ICON;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canCreate(@NotNull ArtifactEditorContext context, @NotNull Artifact artifact) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<? extends ExtractedDirectoryPackagingElement> chooseAndCreate(@NotNull ArtifactEditorContext context, @NotNull Artifact artifact,
|
||||
@NotNull CompositePackagingElement<?> parent) {
|
||||
final FileChooserDescriptor descriptor = new FileChooserDescriptor(false, true, true, false, true, true) {
|
||||
@Override
|
||||
public boolean isFileSelectable(VirtualFile file) {
|
||||
if (file.isInLocalFileSystem() && file.isDirectory()) return false;
|
||||
return super.isFileSelectable(file);
|
||||
}
|
||||
};
|
||||
final FileChooserDialog chooser = FileChooserFactory.getInstance().createFileChooser(descriptor, context.getProject());
|
||||
final VirtualFile[] files = chooser.choose(null, context.getProject());
|
||||
final List<ExtractedDirectoryPackagingElement> list = new ArrayList<ExtractedDirectoryPackagingElement>();
|
||||
for (VirtualFile file : files) {
|
||||
final String fullPath = file.getPath();
|
||||
final int jarEnd = fullPath.indexOf(JarFileSystem.JAR_SEPARATOR);
|
||||
list.add(new ExtractedDirectoryPackagingElement(fullPath.substring(0, jarEnd), fullPath.substring(jarEnd + 1)));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ExtractedDirectoryPackagingElement createEmpty(@NotNull Project project) {
|
||||
return new ExtractedDirectoryPackagingElement();
|
||||
}
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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.packaging.impl.elements;
|
||||
|
||||
import com.intellij.compiler.ant.Generator;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.JarFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.packaging.artifacts.ArtifactType;
|
||||
import com.intellij.packaging.elements.*;
|
||||
import com.intellij.packaging.impl.ui.ExtractedDirectoryPresentation;
|
||||
import com.intellij.packaging.ui.ArtifactEditorContext;
|
||||
import com.intellij.packaging.ui.PackagingElementPresentation;
|
||||
import com.intellij.util.xmlb.annotations.Attribute;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ExtractedDirectoryPackagingElement extends FileOrDirectoryCopyPackagingElement<ExtractedDirectoryPackagingElement> {
|
||||
private String myPathInJar;
|
||||
|
||||
public ExtractedDirectoryPackagingElement() {
|
||||
super(PackagingElementFactoryImpl.EXTRACTED_DIRECTORY_ELEMENT_TYPE);
|
||||
}
|
||||
|
||||
public ExtractedDirectoryPackagingElement(String jarPath, String pathInJar) {
|
||||
super(PackagingElementFactoryImpl.EXTRACTED_DIRECTORY_ELEMENT_TYPE, jarPath);
|
||||
myPathInJar = pathInJar;
|
||||
if (!StringUtil.startsWithChar(myPathInJar, '/')) {
|
||||
myPathInJar = "/" + myPathInJar;
|
||||
}
|
||||
if (!StringUtil.endsWithChar(myPathInJar, '/')) {
|
||||
myPathInJar += "/";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackagingElementPresentation createPresentation(@NotNull ArtifactEditorContext context) {
|
||||
return new ExtractedDirectoryPresentation(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualFile findFile() {
|
||||
final VirtualFile jarFile = super.findFile();
|
||||
if (jarFile == null) return null;
|
||||
|
||||
final VirtualFile jarRoot = JarFileSystem.getInstance().getJarRootForLocalFile(jarFile);
|
||||
if ("/".equals(myPathInJar)) return jarRoot;
|
||||
return jarRoot != null ? jarRoot.findFileByRelativePath(myPathInJar) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends Generator> computeAntInstructions(@NotNull PackagingElementResolvingContext resolvingContext,
|
||||
@NotNull AntCopyInstructionCreator creator,
|
||||
@NotNull ArtifactAntGenerationContext generationContext,
|
||||
@NotNull ArtifactType artifactType) {
|
||||
final String jarPath = generationContext.getSubstitutedPath(myFilePath);
|
||||
return Collections.singletonList(creator.createExtractedDirectoryInstruction(jarPath, StringUtil.trimStart(myPathInJar, "/")));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void computeIncrementalCompilerInstructions(@NotNull IncrementalCompilerInstructionCreator creator,
|
||||
@NotNull PackagingElementResolvingContext resolvingContext,
|
||||
@NotNull ArtifactIncrementalCompilerContext compilerContext,
|
||||
@NotNull ArtifactType artifactType) {
|
||||
final VirtualFile file = findFile();
|
||||
if (file != null && file.isValid() && file.isDirectory()) {
|
||||
creator.addDirectoryCopyInstructions(file);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEqualTo(@NotNull PackagingElement<?> element) {
|
||||
return element instanceof ExtractedDirectoryPackagingElement && super.isEqualTo(element)
|
||||
&& Comparing.equal(myPathInJar, ((ExtractedDirectoryPackagingElement)element).getPathInJar());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtractedDirectoryPackagingElement getState() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(ExtractedDirectoryPackagingElement state) {
|
||||
myFilePath = state.getFilePath();
|
||||
myPathInJar = state.getPathInJar();
|
||||
}
|
||||
|
||||
@Attribute("path-in-jar")
|
||||
public String getPathInJar() {
|
||||
return myPathInJar;
|
||||
}
|
||||
|
||||
public void setPathInJar(String pathInJar) {
|
||||
myPathInJar = pathInJar;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -58,7 +58,7 @@ public class FileCopyPackagingElement extends FileOrDirectoryCopyPackagingElemen
|
||||
}
|
||||
|
||||
public PackagingElementPresentation createPresentation(@NotNull ArtifactEditorContext context) {
|
||||
return new FileCopyPresentation(myFilePath, getOutputFileName(), context);
|
||||
return new FileCopyPresentation(myFilePath, getOutputFileName());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+9
-1
@@ -51,11 +51,12 @@ public class PackagingElementFactoryImpl extends PackagingElementFactory {
|
||||
public static final PackagingElementType<ArchivePackagingElement> ARCHIVE_ELEMENT_TYPE = new ArchiveElementType();
|
||||
public static final PackagingElementType<FileCopyPackagingElement> FILE_COPY_ELEMENT_TYPE = new FileCopyElementType();
|
||||
public static final PackagingElementType<DirectoryCopyPackagingElement> DIRECTORY_COPY_ELEMENT_TYPE = new DirectoryCopyElementType();
|
||||
public static final PackagingElementType<ExtractedDirectoryPackagingElement> EXTRACTED_DIRECTORY_ELEMENT_TYPE = new ExtractedDirectoryElementType();
|
||||
public static final PackagingElementType<ArtifactRootElement<?>> ARTIFACT_ROOT_ELEMENT_TYPE = new ArtifactRootElementType();
|
||||
private static final PackagingElementType[] STANDARD_TYPES = {
|
||||
DIRECTORY_ELEMENT_TYPE, ARCHIVE_ELEMENT_TYPE,
|
||||
LibraryElementType.LIBRARY_ELEMENT_TYPE, ModuleOutputElementType.MODULE_OUTPUT_ELEMENT_TYPE,
|
||||
ArtifactElementType.ARTIFACT_ELEMENT_TYPE, FILE_COPY_ELEMENT_TYPE, DIRECTORY_COPY_ELEMENT_TYPE
|
||||
ArtifactElementType.ARTIFACT_ELEMENT_TYPE, FILE_COPY_ELEMENT_TYPE, DIRECTORY_COPY_ELEMENT_TYPE, EXTRACTED_DIRECTORY_ELEMENT_TYPE
|
||||
};
|
||||
|
||||
@NotNull
|
||||
@@ -253,6 +254,13 @@ public class PackagingElementFactoryImpl extends PackagingElementFactory {
|
||||
return createParentDirectories(relativeOutputPath, new DirectoryCopyPackagingElement(filePath));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public PackagingElement<?> createExtractedDirectoryWithParentDirectories(@NotNull String jarPath, @NotNull String pathInJar,
|
||||
@NotNull String relativeOutputPath) {
|
||||
return createParentDirectories(relativeOutputPath, new ExtractedDirectoryPackagingElement(jarPath, pathInJar));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PackagingElement<?> createFileCopyWithParentDirectories(@NotNull String filePath, @NotNull String relativeOutputPath) {
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.packaging.impl.ui;
|
||||
|
||||
import com.intellij.ide.projectView.PresentationData;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.packaging.impl.elements.ExtractedDirectoryElementType;
|
||||
import com.intellij.packaging.impl.elements.ExtractedDirectoryPackagingElement;
|
||||
import com.intellij.packaging.ui.PackagingElementPresentation;
|
||||
import com.intellij.packaging.ui.PackagingElementWeights;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.util.PathUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ExtractedDirectoryPresentation extends PackagingElementPresentation {
|
||||
private final String myJarPath;
|
||||
private final String myPathInJar;
|
||||
private final VirtualFile myFile;
|
||||
|
||||
public ExtractedDirectoryPresentation(ExtractedDirectoryPackagingElement element) {
|
||||
myFile = element.findFile();
|
||||
myJarPath = element.getFilePath();
|
||||
myPathInJar = element.getPathInJar();
|
||||
}
|
||||
|
||||
public String getPresentableName() {
|
||||
return PathUtil.getFileName(myJarPath) + myPathInJar;
|
||||
}
|
||||
|
||||
public void render(@NotNull PresentationData presentationData, SimpleTextAttributes mainAttributes, SimpleTextAttributes commentAttributes) {
|
||||
presentationData.setIcons(ExtractedDirectoryElementType.EXTRACTED_FOLDER_ICON);
|
||||
final String parentPath = PathUtil.getParentPath(myJarPath);
|
||||
if (myFile == null || !myFile.isDirectory()) {
|
||||
mainAttributes = SimpleTextAttributes.ERROR_ATTRIBUTES;
|
||||
final VirtualFile parentFile = LocalFileSystem.getInstance().findFileByPath(parentPath);
|
||||
if (parentFile == null) {
|
||||
commentAttributes = SimpleTextAttributes.ERROR_ATTRIBUTES;
|
||||
}
|
||||
}
|
||||
presentationData.addText("Unpacked '" + PathUtil.getFileName(myJarPath) + myPathInJar + "'", mainAttributes);
|
||||
presentationData.addText(" (" + parentPath + ")", commentAttributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWeight() {
|
||||
return PackagingElementWeights.EXTRACTED_DIRECTORY;
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.packaging.impl.elements.FileCopyElementType;
|
||||
import com.intellij.packaging.ui.ArtifactEditorContext;
|
||||
import com.intellij.packaging.ui.PackagingElementPresentation;
|
||||
import com.intellij.packaging.ui.PackagingElementWeights;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
@@ -33,12 +32,10 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class FileCopyPresentation extends PackagingElementPresentation {
|
||||
private final String mySourcePath;
|
||||
private final String myOutputFileName;
|
||||
private final ArtifactEditorContext myContext;
|
||||
private final VirtualFile myFile;
|
||||
|
||||
public FileCopyPresentation(String filePath, String outputFileName, ArtifactEditorContext context) {
|
||||
public FileCopyPresentation(String filePath, String outputFileName) {
|
||||
myOutputFileName = outputFileName;
|
||||
myContext = context;
|
||||
|
||||
String parentPath;
|
||||
myFile = LocalFileSystem.getInstance().findFileByPath(filePath);
|
||||
@@ -65,7 +62,7 @@ public class FileCopyPresentation extends PackagingElementPresentation {
|
||||
|
||||
public void render(@NotNull PresentationData presentationData, SimpleTextAttributes mainAttributes, SimpleTextAttributes commentAttributes) {
|
||||
if (myFile != null && !myFile.isDirectory()) {
|
||||
presentationData.setIcons(myFile != null ? myFile.getIcon() : FileCopyElementType.ICON);
|
||||
presentationData.setIcons(myFile.getIcon());
|
||||
presentationData.addText(myOutputFileName, mainAttributes);
|
||||
presentationData.addText(" (" + mySourcePath + ")", commentAttributes);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.intellij.compiler.ant.taskdefs;
|
||||
|
||||
import com.intellij.compiler.ant.Tag;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
/**
|
||||
@@ -27,8 +26,7 @@ import org.jetbrains.annotations.NonNls;
|
||||
public class Include extends Tag {
|
||||
|
||||
public Include(@NonNls final String name) {
|
||||
//noinspection HardCodedStringLiteral
|
||||
super("include", new Pair[] {new Pair<String, String>("name", name)});
|
||||
super("include", pair("name", name));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.intellij.compiler.ant.taskdefs;
|
||||
|
||||
import com.intellij.compiler.ant.Tag;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
/**
|
||||
@@ -26,7 +25,6 @@ import org.jetbrains.annotations.NonNls;
|
||||
*/
|
||||
public class PatternSet extends Tag{
|
||||
public PatternSet(@NonNls final String id) {
|
||||
//noinspection HardCodedStringLiteral
|
||||
super("patternset", new Pair[] {new Pair<String, String>("id", id)});
|
||||
super("patternset", pair("id", id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.compiler.ant.taskdefs;
|
||||
|
||||
import com.intellij.compiler.ant.Tag;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class Unzip extends Tag {
|
||||
public Unzip(String archivePath, String dest) {
|
||||
super("unzip", pair("src", archivePath), pair("dest", dest));
|
||||
}
|
||||
}
|
||||
@@ -17,9 +17,11 @@
|
||||
package com.intellij.compiler.ant.taskdefs;
|
||||
|
||||
import com.intellij.compiler.ant.Tag;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
@@ -31,12 +33,23 @@ import java.io.File;
|
||||
public class ZipFileSet extends Tag{
|
||||
public static final ZipFileSet[] EMPTY_ARRAY = new ZipFileSet[0];
|
||||
|
||||
private ZipFileSet(@NonNls String tagName, Pair... tagOptions) {
|
||||
super(tagName, tagOptions);
|
||||
}
|
||||
|
||||
public ZipFileSet(@NonNls String fileOrDir, @NonNls final String relativePath, boolean isDir) {
|
||||
super("zipfileset",
|
||||
pair(isDir ? "dir" : "file", fileOrDir),
|
||||
pair("prefix", prefix(isDir, relativePath)));
|
||||
}
|
||||
|
||||
public static ZipFileSet createUnpackedSet(@NonNls String zipFilePath, @NotNull String relativePath, final boolean isDir, String pattern) {
|
||||
return new ZipFileSet("zipfileset",
|
||||
pair("src", zipFilePath),
|
||||
pair("prefix", prefix(isDir, relativePath)),
|
||||
pair("includes", pattern));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String prefix(final boolean isDir, final String relativePath) {
|
||||
String path;
|
||||
|
||||
+6
-3
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
package com.intellij.packaging.elements;
|
||||
|
||||
import com.intellij.compiler.ant.Tag;
|
||||
import com.intellij.compiler.ant.Generator;
|
||||
import com.intellij.compiler.ant.Tag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -32,8 +32,11 @@ public interface AntCopyInstructionCreator {
|
||||
Tag createFileCopyInstruction(@NotNull String filePath, String outputFileName);
|
||||
|
||||
@NotNull
|
||||
AntCopyInstructionCreator subFolder(String directoryName);
|
||||
AntCopyInstructionCreator subFolder(@NotNull String directoryName);
|
||||
|
||||
@Nullable
|
||||
Generator createSubFolderCommand(String directoryName);
|
||||
Generator createSubFolderCommand(@NotNull String directoryName);
|
||||
|
||||
@NotNull
|
||||
Generator createExtractedDirectoryInstruction(@NotNull String jarPath, @NotNull String pathInJar);
|
||||
}
|
||||
|
||||
@@ -67,6 +67,10 @@ public abstract class PackagingElementFactory {
|
||||
@NotNull
|
||||
public abstract PackagingElement<?> createDirectoryCopyWithParentDirectories(@NotNull String filePath, @NotNull String relativeOutputPath);
|
||||
|
||||
@NotNull
|
||||
public abstract PackagingElement<?> createExtractedDirectoryWithParentDirectories(@NotNull String jarPath, @NotNull String pathInJar,
|
||||
@NotNull String relativeOutputPath);
|
||||
|
||||
@NotNull
|
||||
public abstract PackagingElement<?> createFileCopyWithParentDirectories(@NotNull String filePath, @NotNull String relativeOutputPath,
|
||||
@Nullable String outputFileName);
|
||||
|
||||
@@ -22,6 +22,7 @@ public class PackagingElementWeights {
|
||||
public static final int ARTIFACT = 100;
|
||||
public static final int DIRECTORY = 50;
|
||||
public static final int DIRECTORY_COPY = 40;
|
||||
public static final int EXTRACTED_DIRECTORY = 39;
|
||||
public static final int LIBRARY = 30;
|
||||
public static final int MODULE = 20;
|
||||
public static final int FACET = 10;
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.ILazyParseableElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -43,6 +44,9 @@ public class DeclarationParser {
|
||||
private static final TokenSet APPEND_TO_METHOD_SET = TokenSet.create(
|
||||
JavaTokenType.IDENTIFIER, JavaTokenType.COMMA, JavaTokenType.THROWS_KEYWORD);
|
||||
|
||||
private static final String WHITESPACES = "\n\r \t";
|
||||
private static final String LINE_ENDS = "\n\r";
|
||||
|
||||
private DeclarationParser() { }
|
||||
|
||||
public static void parseClassBodyWithBraces(final PsiBuilder builder, final boolean isAnnotation, final boolean isEnum) {
|
||||
@@ -209,6 +213,7 @@ public class DeclarationParser {
|
||||
}
|
||||
|
||||
final PsiBuilder.Marker declaration = builder.mark();
|
||||
final int declarationStart = builder.getCurrentOffset();
|
||||
|
||||
final Pair<PsiBuilder.Marker, Boolean> modListInfo = parseModifierList(builder);
|
||||
final PsiBuilder.Marker modList = modListInfo.first;
|
||||
@@ -225,7 +230,7 @@ public class DeclarationParser {
|
||||
else if (ElementType.CLASS_KEYWORD_BIT_SET.contains(builder.getTokenType())) {
|
||||
final PsiBuilder.Marker root = parseClassFromKeyword(builder, declaration, false);
|
||||
if (context == Context.FILE) {
|
||||
// todo: append following declarations to root
|
||||
// todo: append following declarations to root (?)
|
||||
boolean declarationsAfterEnd = false;
|
||||
|
||||
while (builder.getTokenType() != null && builder.getTokenType() != JavaTokenType.RBRACE) {
|
||||
@@ -344,7 +349,7 @@ public class DeclarationParser {
|
||||
if (typeParams != null) {
|
||||
typeParams.precede().errorBefore(JavaErrorMessages.message("unexpected.token"), type);
|
||||
}
|
||||
return parseFieldOrLocalVariable(builder, declaration, context);
|
||||
return parseFieldOrLocalVariable(builder, declaration, declarationStart, context);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -538,7 +543,7 @@ public class DeclarationParser {
|
||||
|
||||
@Nullable
|
||||
private static PsiBuilder.Marker parseFieldOrLocalVariable(final PsiBuilder builder, final PsiBuilder.Marker declaration,
|
||||
final Context context) {
|
||||
final int declarationStart, final Context context) {
|
||||
final IElementType varType;
|
||||
if (context == Context.CLASS || context == Context.ANNOTATION_INTERFACE) {
|
||||
varType = JavaElementType.FIELD;
|
||||
@@ -553,46 +558,66 @@ public class DeclarationParser {
|
||||
}
|
||||
|
||||
PsiBuilder.Marker variable = declaration;
|
||||
boolean openMarker = true;
|
||||
boolean unclosed = false;
|
||||
boolean eatSemicolon = true;
|
||||
boolean expectSemicolon = true;
|
||||
boolean shouldRollback;
|
||||
boolean openMarker = true;
|
||||
while (true) {
|
||||
shouldRollback = true;
|
||||
|
||||
if (!eatBrackets(builder)) {
|
||||
expectSemicolon = false;
|
||||
unclosed = true;
|
||||
}
|
||||
|
||||
if (expect(builder, JavaTokenType.EQ)) {
|
||||
final PsiBuilder.Marker expr = ExpressionParser.parse(builder);
|
||||
if (expr == null) {
|
||||
if (expr != null) {
|
||||
shouldRollback = false;
|
||||
}
|
||||
else {
|
||||
error(builder, JavaErrorMessages.message("expected.expression"));
|
||||
expectSemicolon = false;
|
||||
unclosed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (builder.getTokenType() == JavaTokenType.COMMA) {
|
||||
variable.done(varType);
|
||||
builder.advanceLexer();
|
||||
variable = builder.mark();
|
||||
}
|
||||
else {
|
||||
if (builder.getTokenType() != JavaTokenType.COMMA) break;
|
||||
variable.done(varType);
|
||||
builder.advanceLexer();
|
||||
|
||||
if (builder.getTokenType() != JavaTokenType.IDENTIFIER) {
|
||||
error(builder, JavaErrorMessages.message("expected.identifier"));
|
||||
unclosed = true;
|
||||
eatSemicolon = false;
|
||||
openMarker = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!expect(builder, JavaTokenType.IDENTIFIER)) {
|
||||
variable.drop();
|
||||
error(builder, JavaErrorMessages.message("expected.identifier"));
|
||||
openMarker = false;
|
||||
eatSemicolon = false;
|
||||
break;
|
||||
}
|
||||
variable = builder.mark();
|
||||
builder.advanceLexer();
|
||||
}
|
||||
|
||||
if (eatSemicolon) {
|
||||
if (!expect(builder, JavaTokenType.SEMICOLON) && expectSemicolon) {
|
||||
if (builder.getTokenType() == JavaTokenType.SEMICOLON && eatSemicolon) {
|
||||
builder.advanceLexer();
|
||||
}
|
||||
else {
|
||||
// special treatment (see DeclarationParserTest.testMultiLineUnclosed())
|
||||
if (!builder.eof() && shouldRollback) {
|
||||
final CharSequence text = builder.getOriginalText();
|
||||
final int spaceEnd = builder.getCurrentOffset();
|
||||
final int spaceStart = CharArrayUtil.shiftBackward(text, spaceEnd-1, WHITESPACES);
|
||||
final int lineStart = CharArrayUtil.shiftBackwardUntil(text, spaceEnd, LINE_ENDS);
|
||||
|
||||
if (declarationStart < lineStart && lineStart < spaceStart) {
|
||||
final int newBufferEnd = CharArrayUtil.shiftForward(text, lineStart, WHITESPACES);
|
||||
declaration.rollbackTo();
|
||||
return parse(stoppingBuilder(builder, newBufferEnd), context);
|
||||
}
|
||||
}
|
||||
|
||||
if (!unclosed) {
|
||||
error(builder, JavaErrorMessages.message("expected.semicolon"));
|
||||
}
|
||||
// todo: special treatment - see DeclarationParserTest.testMultiLineUnclosed()
|
||||
}
|
||||
|
||||
if (openMarker) {
|
||||
|
||||
@@ -107,6 +107,25 @@ public class JavaParserUtil {
|
||||
}
|
||||
return (braceCount == 0 ? null : tokenType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eof() {
|
||||
return braceCount == 0 || super.eof();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static PsiBuilder stoppingBuilder(final PsiBuilder builder, final int stopAt) {
|
||||
return new PsiBuilderAdapter(builder) {
|
||||
@Override
|
||||
public IElementType getTokenType() {
|
||||
return getCurrentOffset() < stopAt ? super.getTokenType() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eof() {
|
||||
return getCurrentOffset() < stopAt || super.eof();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.augment.PsiAugmentProvider;
|
||||
import com.intellij.psi.filters.OrFilter;
|
||||
import com.intellij.psi.impl.compiled.ClsElementImpl;
|
||||
import com.intellij.psi.impl.source.PsiImmediateClassType;
|
||||
@@ -39,10 +38,7 @@ import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.ui.IconDeferrer;
|
||||
import com.intellij.ui.RowIcon;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.ReflectionCache;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -864,6 +860,7 @@ public class PsiClassImplUtil {
|
||||
}
|
||||
|
||||
public static boolean isClassEquivalentTo(PsiClass aClass, PsiElement another) {
|
||||
if (aClass == another) return true;
|
||||
if (!(another instanceof PsiClass)) return false;
|
||||
String name1 = aClass.getName();
|
||||
if (name1 == null) return false;
|
||||
@@ -900,17 +897,13 @@ public class PsiClassImplUtil {
|
||||
|
||||
final PsiFile file1 = aClass.getContainingFile().getOriginalFile();
|
||||
final PsiFile file2 = another.getContainingFile().getOriginalFile();
|
||||
if (file1.equals(file2)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//see com.intellij.openapi.vcs.changes.PsiChangeTracker
|
||||
//see com.intellij.psi.impl.PsiFileFactoryImpl#createFileFromText(CharSequence,PsiFile)
|
||||
final PsiFile original1 = file1.getUserData(PsiFileFactory.ORIGINAL_FILE);
|
||||
final PsiFile original2 = file2.getUserData(PsiFileFactory.ORIGINAL_FILE);
|
||||
if (original1 == original2 && original1 != null
|
||||
|| original1 == file2 || original2 == file1) {
|
||||
return true;
|
||||
if (original1 == original2 && original1 != null || original1 == file2 || original2 == file1 || file1 == file2) {
|
||||
return compareClassSeqNumber(aClass, (PsiClass)another);
|
||||
}
|
||||
|
||||
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(aClass.getProject()).getFileIndex();
|
||||
@@ -920,6 +913,28 @@ public class PsiClassImplUtil {
|
||||
(fileIndex.isInSource(vfile2) || fileIndex.isInLibraryClasses(vfile2));
|
||||
}
|
||||
|
||||
private static boolean compareClassSeqNumber(PsiClass aClass, PsiClass another) {
|
||||
// there may be several classes in one file, they must not be equal
|
||||
int index1 = getSeqNumber(aClass);
|
||||
if (index1 == -1) return true;
|
||||
int index2 = getSeqNumber(another);
|
||||
return index1 == index2;
|
||||
}
|
||||
|
||||
private static int getSeqNumber(PsiClass aClass) {
|
||||
// sequence number of this class among its parent' child classes named the same
|
||||
PsiElement parent = aClass.getParent();
|
||||
if (parent == null) return -1;
|
||||
int seqNo = 0;
|
||||
for (PsiElement child : parent.getChildren()) {
|
||||
if (child == aClass) return seqNo;
|
||||
if (child instanceof PsiClass && Comparing.strEqual(aClass.getName(), ((PsiClass)child).getName())) {
|
||||
seqNo++;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static PsiElement originalElement(PsiClass aClass) {
|
||||
final PsiElement originalElement = aClass.getOriginalElement();
|
||||
final PsiCompiledElement compiled = originalElement.getUserData(ClsElementImpl.COMPILED_ELEMENT);
|
||||
|
||||
+10
-1
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiManagerEx;
|
||||
import com.intellij.psi.impl.PsiSubstitutorImpl;
|
||||
import com.intellij.psi.impl.search.JavaDirectInheritorsSearcher;
|
||||
import com.intellij.psi.impl.source.resolve.ResolveCache;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.impl.source.tree.TreeElement;
|
||||
@@ -167,7 +168,15 @@ public class ClsJavaCodeReferenceElementImpl extends ClsElementImpl implements P
|
||||
for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable((PsiTypeParameterListOwner)element)) {
|
||||
if (myQualifiedName.equals(parameter.getName())) return parameter;
|
||||
}
|
||||
return JavaPsiFacade.getInstance(getProject()).findClass(myQualifiedName, getResolveScope());
|
||||
return resolveClassPreferringMyJar();
|
||||
}
|
||||
|
||||
private PsiClass resolveClassPreferringMyJar() {
|
||||
PsiClass[] classes = JavaPsiFacade.getInstance(getProject()).findClasses(myQualifiedName, getResolveScope());
|
||||
for (PsiClass aClass : classes) {
|
||||
if (JavaDirectInheritorsSearcher.isFromTheSameJar(aClass, this)) return aClass;
|
||||
}
|
||||
return classes.length == 0 ? null : classes[0];
|
||||
}
|
||||
|
||||
public void processVariants(PsiScopeProcessor processor) {
|
||||
|
||||
@@ -8,6 +8,8 @@ import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.JarFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiManagerImpl;
|
||||
import com.intellij.psi.impl.java.stubs.index.JavaAnonymousClassBaseRefOccurenceIndex;
|
||||
@@ -19,14 +21,17 @@ import com.intellij.psi.search.searches.AllClassesSearch;
|
||||
import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, DirectClassInheritorsSearch.SearchParameters> {
|
||||
|
||||
public boolean execute(final DirectClassInheritorsSearch.SearchParameters p, final Processor<PsiClass> consumer) {
|
||||
final PsiClass aClass = p.getClassToProcess();
|
||||
final PsiManagerImpl psiManager = (PsiManagerImpl)PsiManager.getInstance(aClass.getProject());
|
||||
@@ -73,10 +78,22 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
|
||||
}
|
||||
});
|
||||
|
||||
Map<String, List<PsiClass>> classes = new HashMap<String, List<PsiClass>>();
|
||||
|
||||
for (PsiReferenceList referenceList : candidates) {
|
||||
ProgressManager.checkCanceled();
|
||||
PsiClass candidate = (PsiClass)referenceList.getParent();
|
||||
if (!consumer.process(candidate)) return false;
|
||||
String fqn = candidate.getQualifiedName();
|
||||
List<PsiClass> list = classes.get(fqn);
|
||||
if (list == null) {
|
||||
list = new ArrayList<PsiClass>();
|
||||
classes.put(fqn, list);
|
||||
}
|
||||
list.add(candidate);
|
||||
}
|
||||
|
||||
for (List<PsiClass> sameNamedClasses : classes.values()) {
|
||||
if (!processSameNamedClasses(consumer, aClass, sameNamedClasses)) return false;
|
||||
}
|
||||
|
||||
if (p.includeAnonymous()) {
|
||||
@@ -116,4 +133,37 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean processSameNamedClasses(Processor<PsiClass> consumer, PsiClass aClass, List<PsiClass> sameNamedClasses) {
|
||||
// if there is a class from the same jar, prefer it
|
||||
boolean sameJarClassFound = false;
|
||||
for (PsiClass sameNamedClass : sameNamedClasses) {
|
||||
boolean fromSameJar = isFromTheSameJar(sameNamedClass, aClass);
|
||||
if (fromSameJar) {
|
||||
sameJarClassFound = true;
|
||||
if (!consumer.process(sameNamedClass)) return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sameJarClassFound) {
|
||||
for (PsiClass sameNamedClass : sameNamedClasses) {
|
||||
if (!consumer.process(sameNamedClass)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static VirtualFile getJarFile(PsiElement candidate) {
|
||||
VirtualFile file = candidate.getContainingFile().getVirtualFile();
|
||||
if (file != null && file.getFileSystem() instanceof JarFileSystem) {
|
||||
return JarFileSystem.getInstance().getVirtualFileForJar(file);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
public static boolean isFromTheSameJar(PsiElement candidate, PsiElement other) {
|
||||
VirtualFile c1 = getJarFile(candidate);
|
||||
VirtualFile c2 = getJarFile(other);
|
||||
return c1 != null && c1 == c2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.intellij.psi.impl.source.codeStyle.CodeEditUtil;
|
||||
import com.intellij.psi.impl.source.jsp.JspContextManager;
|
||||
import com.intellij.psi.impl.source.jsp.jspJava.JspCodeBlock;
|
||||
import com.intellij.psi.impl.source.tree.*;
|
||||
import com.intellij.psi.jsp.BaseJspFile;
|
||||
import com.intellij.psi.jsp.JspElementType;
|
||||
import com.intellij.psi.jsp.JspFile;
|
||||
import com.intellij.psi.jsp.JspSpiUtil;
|
||||
@@ -289,10 +290,10 @@ public class PsiLocalVariableImpl extends CompositePsiElement implements PsiLoca
|
||||
}
|
||||
|
||||
final Set<PsiFile> allIncluded = new THashSet<PsiFile>(10);
|
||||
final JspFile rootContext = contextManager.getRootContextFile(jspFile);
|
||||
final BaseJspFile rootContext = contextManager.getRootContextFile(jspFile);
|
||||
allIncluded.add(rootContext);
|
||||
JspSpiUtil.visitAllIncludedFilesRecursively(rootContext, new Processor<JspFile>() {
|
||||
public boolean process(final JspFile file) {
|
||||
JspSpiUtil.visitAllIncludedFilesRecursively(rootContext, new Processor<BaseJspFile>() {
|
||||
public boolean process(final BaseJspFile file) {
|
||||
allIncluded.add(file);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ PsiJavaFile:MultiLineUnclosed.java
|
||||
PsiKeyword:int('int')
|
||||
PsiErrorElement:Identifier expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' \n ')
|
||||
PsiWhiteSpace(' \n ')
|
||||
PsiField:o
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
|
||||
+1
-2
@@ -21,7 +21,6 @@ import com.intellij.lang.java.parser.JavaParsingTestCase;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
|
||||
|
||||
// todo: fix parser and uncomment tests
|
||||
public class DeclarationParserTest extends JavaParsingTestCase {
|
||||
public DeclarationParserTest() {
|
||||
super("parser-partial/declarations");
|
||||
@@ -78,7 +77,7 @@ public class DeclarationParserTest extends JavaParsingTestCase {
|
||||
public void testUnclosedComma() { doParserTest("{ int field, }", false, false); }
|
||||
public void testUnclosedSemicolon() { doParserTest("{ int field }", false, false); }
|
||||
public void testMissingInitializerExpression() { doParserTest("{ int field=; }", false, false); }
|
||||
//public void testMultiLineUnclosed() { doParserTest("{ int \n Object o; }", false, false); }
|
||||
public void testMultiLineUnclosed() { doParserTest("{ int \n Object o; }", false, false); }
|
||||
|
||||
public void testMethodNormal0() { doParserTest("{ void f() {} }", false, false); }
|
||||
public void testMethodNormal1() { doParserTest("{ void f(); }", false, false); }
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.psi.impl.source.jsp;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.jsp.BaseJspFile;
|
||||
import com.intellij.psi.jsp.JspFile;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -32,20 +33,22 @@ public abstract class JspContextManager {
|
||||
return project.getComponent(JspContextManager.class);
|
||||
}
|
||||
|
||||
public abstract JspFile[] getSuitableContextFiles(@NotNull PsiFile file);
|
||||
public abstract BaseJspFile[] getSuitableContextFiles(@NotNull PsiFile file);
|
||||
|
||||
public abstract void setContextFile(@NotNull PsiFile file, @Nullable JspFile contextFile, final boolean userDefined);
|
||||
public abstract void setContextFile(@NotNull PsiFile file, @Nullable BaseJspFile contextFile);
|
||||
|
||||
public abstract @Nullable JspFile getContextFile(@NotNull PsiFile file);
|
||||
public abstract @Nullable
|
||||
BaseJspFile getContextFile(@NotNull PsiFile file);
|
||||
|
||||
public abstract @Nullable JspFile getConfiguredContextFile(@NotNull PsiFile file);
|
||||
|
||||
public @NotNull JspFile getRootContextFile(@NotNull JspFile file) {
|
||||
JspFile rootContext = file;
|
||||
HashSet<JspFile> recursionPreventer = new HashSet<JspFile>();
|
||||
public @NotNull
|
||||
BaseJspFile getRootContextFile(@NotNull BaseJspFile file) {
|
||||
BaseJspFile rootContext = file;
|
||||
HashSet<BaseJspFile> recursionPreventer = new HashSet<BaseJspFile>();
|
||||
do {
|
||||
recursionPreventer.add(rootContext);
|
||||
JspFile context = getContextFile(rootContext);
|
||||
BaseJspFile context = getContextFile(rootContext);
|
||||
if (context == null || recursionPreventer.contains(context)) break;
|
||||
rootContext = context;
|
||||
}
|
||||
|
||||
@@ -62,14 +62,14 @@ public abstract class JspSpiUtil {
|
||||
|
||||
protected abstract int _escapeCharsInJspContext(JspFile file, int offset, String toEscape) throws IncorrectOperationException;
|
||||
|
||||
public static void visitAllIncludedFilesRecursively(JspFile jspFile, Processor<JspFile> visitor) {
|
||||
public static void visitAllIncludedFilesRecursively(BaseJspFile jspFile, Processor<BaseJspFile> visitor) {
|
||||
final JspSpiUtil util = getJspSpiUtil();
|
||||
if (util != null) {
|
||||
util._visitAllIncludedFilesRecursively(jspFile, visitor);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void _visitAllIncludedFilesRecursively(JspFile jspFile, Processor<JspFile> visitor);
|
||||
protected abstract void _visitAllIncludedFilesRecursively(BaseJspFile jspFile, Processor<BaseJspFile> visitor);
|
||||
|
||||
@Nullable
|
||||
public static PsiElement resolveMethodPropertyReference(@NotNull PsiReference reference, @Nullable PsiClass resolvedClass, boolean readable) {
|
||||
|
||||
@@ -919,8 +919,9 @@ public class TypeConversionUtil {
|
||||
substitutor = getSuperClassSubstitutorInner(superClass, derivedClass, derivedSubstitutor, visited, manager);
|
||||
}
|
||||
if (substitutor == null) {
|
||||
LOG.error("Not inheritor: " + derivedClass + "(" + derivedClass.getClass().getName() + ");" +
|
||||
" super: " + superClass + "(" + derivedClass.getClass().getName() + ")");
|
||||
LOG.error(
|
||||
"Not inheritor: " + derivedClass + "(" + derivedClass.getClass().getName() + "; " + PsiUtil.getVirtualFile(derivedClass) + ");" +
|
||||
"\n super: " + superClass + "(" + superClass.getClass().getName() + "; " + PsiUtil.getVirtualFile(superClass) + ")");
|
||||
}
|
||||
return substitutor;
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 727 B After Width: | Height: | Size: 588 B |
Binary file not shown.
|
After Width: | Height: | Size: 657 B |
@@ -35,16 +35,12 @@ public class FileIncludeInfo {
|
||||
this.runtimeOnly = runtimeOnly;
|
||||
}
|
||||
|
||||
public FileIncludeInfo(@NotNull String fileName, @NotNull String path, int offset) {
|
||||
this(fileName, path, offset, false);
|
||||
}
|
||||
|
||||
public FileIncludeInfo(@NotNull String fileName, @NotNull String path) {
|
||||
this(fileName, path, -1, false);
|
||||
public FileIncludeInfo(@NotNull String path, int offset) {
|
||||
this(getFileName(path), path, offset, false);
|
||||
}
|
||||
|
||||
public FileIncludeInfo(@NotNull String path) {
|
||||
this(getFileName(path), path, -1, false);
|
||||
this(path, -1);
|
||||
}
|
||||
|
||||
private static String getFileName(String path) {
|
||||
|
||||
@@ -18,9 +18,11 @@ package com.intellij.psi.impl.include;
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiFileSystemItem;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
@@ -36,6 +38,8 @@ public abstract class FileIncludeManager {
|
||||
|
||||
public abstract VirtualFile[] getIncludingFiles(VirtualFile file, boolean compileTimeOnly);
|
||||
|
||||
public abstract void processIncludingFiles(PsiFile context, Processor<Pair<VirtualFile, FileIncludeInfo>> processor);
|
||||
|
||||
@Nullable
|
||||
public abstract PsiFileSystemItem resolveFileReference(String text, PsiFile context);
|
||||
public abstract PsiFileSystemItem resolveFileInclude(FileIncludeInfo info, PsiFile context);
|
||||
}
|
||||
|
||||
@@ -229,6 +229,16 @@ public class PsiTreeUtil {
|
||||
return result == null ? null : ArrayUtil.toObjectArray(result, aClass);
|
||||
}
|
||||
|
||||
@NotNull public static <T extends PsiElement> List<T> getChildrenOfTypeAsList(@NotNull PsiElement element, @NotNull Class<T> aClass) {
|
||||
List<T> result = new SmartList<T>();
|
||||
for(PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()){
|
||||
if (instanceOf(aClass, child)) {
|
||||
result.add((T)child);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static boolean instanceOf(final Class aClass, final PsiElement child) {
|
||||
/*
|
||||
@@ -580,7 +590,8 @@ public class PsiTreeUtil {
|
||||
while (true);
|
||||
}
|
||||
|
||||
public static PsiElement prevLeaf(PsiElement current){
|
||||
@Nullable
|
||||
public static PsiElement prevLeaf(@NotNull PsiElement current){
|
||||
final PsiElement prevSibling = current.getPrevSibling();
|
||||
if(prevSibling != null) return lastChild(prevSibling);
|
||||
final PsiElement parent = current.getParent();
|
||||
@@ -588,7 +599,8 @@ public class PsiTreeUtil {
|
||||
return prevLeaf(parent);
|
||||
}
|
||||
|
||||
public static PsiElement nextLeaf(PsiElement current){
|
||||
@Nullable
|
||||
public static PsiElement nextLeaf(@NotNull PsiElement current){
|
||||
final PsiElement nextSibling = current.getNextSibling();
|
||||
if(nextSibling != null) return firstChild(nextSibling);
|
||||
final PsiElement parent = current.getParent();
|
||||
@@ -602,17 +614,20 @@ public class PsiTreeUtil {
|
||||
return element;
|
||||
}
|
||||
|
||||
public static PsiElement firstChild(final PsiElement element) {
|
||||
if(element.getFirstChild() != null) return firstChild(element.getFirstChild());
|
||||
public static PsiElement firstChild(@NotNull final PsiElement element) {
|
||||
PsiElement child = element.getFirstChild();
|
||||
if(child != null) return firstChild(child);
|
||||
return element;
|
||||
}
|
||||
|
||||
public static PsiElement prevLeaf(final PsiErrorElement element, final boolean skipEmptyElements) {
|
||||
@Nullable
|
||||
public static PsiElement prevLeaf(@NotNull final PsiErrorElement element, final boolean skipEmptyElements) {
|
||||
PsiElement prevLeaf = prevLeaf(element);
|
||||
while (skipEmptyElements && prevLeaf != null && prevLeaf.getTextLength() == 0) prevLeaf = prevLeaf(prevLeaf);
|
||||
return prevLeaf;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement nextLeaf(final PsiErrorElement element, final boolean skipEmptyElements) {
|
||||
PsiElement nextLeaf = nextLeaf(element);
|
||||
while (skipEmptyElements && nextLeaf != null && nextLeaf.getTextLength() == 0) nextLeaf = nextLeaf(nextLeaf);
|
||||
|
||||
+8
-1
@@ -349,7 +349,14 @@ public class CommentByBlockCommentHandler implements CodeInsightActionHandler {
|
||||
else {
|
||||
space = "";
|
||||
}
|
||||
TextRange range = insertNestedComments(chars, startOffset, endOffset, space + commentPrefix + "\n", space + commentSuffix + "\n", commenter);
|
||||
final StringBuilder nestingPrefix = new StringBuilder(space).append(commentPrefix);
|
||||
if (!commentPrefix.endsWith("\n")){
|
||||
nestingPrefix.append("\n");
|
||||
}
|
||||
final StringBuilder nestingSuffix = new StringBuilder(space);
|
||||
nestingSuffix.append(commentSuffix.startsWith("\n") ? commentSuffix.substring(1) : commentSuffix);
|
||||
nestingSuffix.append("\n");
|
||||
TextRange range = insertNestedComments(chars, startOffset, endOffset, nestingPrefix.toString(), nestingSuffix.toString(), commenter);
|
||||
myEditor.getSelectionModel().setSelection(range.getStartOffset(), range.getEndOffset());
|
||||
//myEditor.getSelectionModel().removeSelection();
|
||||
LogicalPosition pos = new LogicalPosition(caretPosition.line + 1, caretPosition.column);
|
||||
|
||||
+9
-2
@@ -224,7 +224,8 @@ public class CommentByLineCommentHandler implements CodeInsightActionHandler {
|
||||
}
|
||||
|
||||
boolean allLineCommented = true;
|
||||
|
||||
boolean commentWithIndent = !CodeStyleSettingsManager.getSettings(myProject).LINE_COMMENT_AT_FIRST_COLUMN;
|
||||
|
||||
for (int line = myStartLine; line <= myEndLine; line++) {
|
||||
Commenter commenter = blockSuitableCommenter != null ? blockSuitableCommenter : findCommenter(line);
|
||||
if (commenter == null) return;
|
||||
@@ -245,12 +246,18 @@ public class CommentByLineCommentHandler implements CodeInsightActionHandler {
|
||||
myCommenters[line - myStartLine] = commenter;
|
||||
if (!isLineCommented(line, chars, commenter) && (singleline || !isLineEmpty(line))) {
|
||||
allLineCommented = false;
|
||||
if (commenter instanceof IndentedCommenter){
|
||||
final Boolean value = ((IndentedCommenter)commenter).forceIndentedLineComment();
|
||||
if (value != null){
|
||||
commentWithIndent = value;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!allLineCommented) {
|
||||
if (CodeStyleSettingsManager.getSettings(myProject).LINE_COMMENT_AT_FIRST_COLUMN) {
|
||||
if (!commentWithIndent) {
|
||||
doDefaultCommenting(blockSuitableCommenter);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.codeInsight.generation;
|
||||
|
||||
import com.intellij.lang.Commenter;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author oleg
|
||||
*/
|
||||
public interface IndentedCommenter extends Commenter {
|
||||
/**
|
||||
* Used to override CodeStyleSetings#LINE_COMMENT_AT_FIRST_COLUMN option
|
||||
* @return true or false to overrride, null to use settings option
|
||||
*/
|
||||
@Nullable
|
||||
Boolean forceIndentedLineComment();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.ide.actions;
|
||||
|
||||
import com.intellij.ide.fileTemplates.FileTemplate;
|
||||
import com.intellij.ide.fileTemplates.FileTemplateManager;
|
||||
import com.intellij.ide.fileTemplates.FileTemplateUtil;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author Dmitry Avdeev
|
||||
*/
|
||||
public abstract class CreateFileFromTemplateAction extends CreateFromTemplateAction<PsiFile> {
|
||||
|
||||
public CreateFileFromTemplateAction(String text, String description, Icon icon) {
|
||||
super(text, description, icon);
|
||||
}
|
||||
|
||||
protected PsiFile createFileFromTemplate(String name, FileTemplate template, PsiDirectory dir) {
|
||||
|
||||
PsiElement element;
|
||||
try {
|
||||
element = FileTemplateUtil
|
||||
.createFromTemplate(template, name, FileTemplateManager.getInstance().getDefaultProperties(), dir);
|
||||
final PsiFile psiFile = element.getContainingFile();
|
||||
|
||||
final VirtualFile virtualFile = psiFile.getVirtualFile();
|
||||
if (virtualFile != null) {
|
||||
FileEditorManager.getInstance(dir.getProject()).openFile(virtualFile, true);
|
||||
String property = getDefaultTemplateProperty();
|
||||
if (property != null) {
|
||||
PropertiesComponent.getInstance(dir.getProject()).setValue(property, template.getName());
|
||||
}
|
||||
return psiFile;
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected PsiFile createFile(String name, String templateName, PsiDirectory dir) {
|
||||
final FileTemplate template = FileTemplateManager.getInstance().getInternalTemplate(templateName);
|
||||
return createFileFromTemplate(name, template, dir);
|
||||
}
|
||||
}
|
||||
@@ -17,19 +17,13 @@ package com.intellij.ide.actions;
|
||||
|
||||
import com.intellij.CommonBundle;
|
||||
import com.intellij.ide.IdeView;
|
||||
import com.intellij.ide.fileTemplates.FileTemplate;
|
||||
import com.intellij.ide.fileTemplates.FileTemplateManager;
|
||||
import com.intellij.ide.fileTemplates.FileTemplateUtil;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -39,37 +33,12 @@ import javax.swing.*;
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public abstract class CreateFromTemplateAction<T extends PsiElement> extends AnAction {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.CreateFromTemplateAction");
|
||||
protected static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.CreateFromTemplateAction");
|
||||
|
||||
public CreateFromTemplateAction(String text, String description, Icon icon) {
|
||||
super(text, description, icon);
|
||||
}
|
||||
|
||||
protected static PsiFile createFileFromTemplate(String name, String templateName, PsiDirectory dir) {
|
||||
final FileTemplate template = FileTemplateManager.getInstance().getInternalTemplate(templateName);
|
||||
|
||||
PsiElement element;
|
||||
try {
|
||||
element = FileTemplateUtil
|
||||
.createFromTemplate(template, name, FileTemplateManager.getInstance().getDefaultProperties(), dir);
|
||||
final PsiFile psiFile = element.getContainingFile();
|
||||
|
||||
final VirtualFile virtualFile = psiFile.getVirtualFile();
|
||||
if (virtualFile != null) {
|
||||
FileEditorManager.getInstance(dir.getProject()).openFile(virtualFile, true);
|
||||
return psiFile;
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public final void actionPerformed(final AnActionEvent e) {
|
||||
final DataContext dataContext = e.getDataContext();
|
||||
|
||||
@@ -105,22 +74,30 @@ public abstract class CreateFromTemplateAction<T extends PsiElement> extends AnA
|
||||
});
|
||||
if (createdElement != null) {
|
||||
view.selectElement(createdElement);
|
||||
postProcesss(createdElement, selectedTemplateName.get());
|
||||
postProcess(createdElement, selectedTemplateName.get());
|
||||
}
|
||||
}
|
||||
|
||||
protected void postProcesss(T createdElement, String templateName) {
|
||||
protected void postProcess(T createdElement, String templateName) {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract T createFile(String name, String templateName, PsiDirectory dir);
|
||||
|
||||
protected abstract void checkBeforeCreate(String name, String templateName, PsiDirectory dir);
|
||||
protected void checkBeforeCreate(String name, String templateName, PsiDirectory dir) {
|
||||
dir.checkCreateFile(name);
|
||||
}
|
||||
|
||||
protected abstract void buildDialog(Project project, PsiDirectory directory, CreateFileFromTemplateDialog.Builder builder);
|
||||
|
||||
@Nullable
|
||||
protected String getDefaultTemplateName(@NotNull PsiDirectory dir) {
|
||||
String property = getDefaultTemplateProperty();
|
||||
return property == null ? null : PropertiesComponent.getInstance(dir.getProject()).getValue(property);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected String getDefaultTemplateProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.ide.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author Dmitry Avdeev
|
||||
*/
|
||||
public abstract class TemplateKindProvider {
|
||||
|
||||
private final static ExtensionPointName<TemplateKindProvider> EP_NAME =
|
||||
ExtensionPointName.create("com.intellij.javaee.templateKindProvider");
|
||||
|
||||
public static void addAdditionalKinds(AnAction action, PsiDirectory dir, CreateFileFromTemplateDialog.Builder builder) {
|
||||
String id = ActionManager.getInstance().getId(action);
|
||||
for (TemplateKindProvider provider : Extensions.getExtensions(EP_NAME)) {
|
||||
for (Kind kind : provider.getAdditionalKinds(dir)) {
|
||||
builder.addKind(kind.name, kind.icon, kind.templateName);
|
||||
}
|
||||
}
|
||||
}
|
||||
public abstract boolean isAvailable(Class<? extends AnAction> actionClass);
|
||||
public abstract Kind[] getAdditionalKinds(PsiDirectory dir);
|
||||
|
||||
public static class Kind {
|
||||
public final String name;
|
||||
public final String templateName;
|
||||
public final Icon icon;
|
||||
|
||||
public Kind(String name, String templateName, Icon icon) {
|
||||
this.name = name;
|
||||
this.templateName = templateName;
|
||||
this.icon = icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -195,7 +195,7 @@ public class EditorWindow implements EditorEx, UserDataHolderEx {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FoldingModel getFoldingModel() {
|
||||
public FoldingModelEx getFoldingModel() {
|
||||
return myFoldingModelWindow;
|
||||
}
|
||||
|
||||
@@ -283,6 +283,11 @@ public class EditorWindow implements EditorEx, UserDataHolderEx {
|
||||
|
||||
@NotNull
|
||||
public LogicalPosition offsetToLogicalPosition(final int offset) {
|
||||
return offsetToLogicalPosition(offset, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public LogicalPosition offsetToLogicalPosition(final int offset, boolean softWrapAware) {
|
||||
assert isValid();
|
||||
int lineNumber = myDocumentWindow.getLineNumber(offset);
|
||||
int lineStartOffset = myDocumentWindow.getLineStartOffset(lineNumber);
|
||||
@@ -465,6 +470,11 @@ public class EditorWindow implements EditorEx, UserDataHolderEx {
|
||||
|
||||
@NotNull
|
||||
public LogicalPosition visualToLogicalPosition(@NotNull final VisualPosition pos) {
|
||||
return visualToLogicalPosition(pos, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public LogicalPosition visualToLogicalPosition(@NotNull final VisualPosition pos, boolean softWrapAware) {
|
||||
assert isValid();
|
||||
return new LogicalPosition(pos.line, pos.column);
|
||||
}
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ public class TogglePopupHintsPanel implements StatusBarWidget, StatusBarWidget.I
|
||||
return "InspectionProfile";
|
||||
}
|
||||
|
||||
public WidgetPresentation getPresentation(@NotNull Type type) {
|
||||
public WidgetPresentation getPresentation(@NotNull PlatformType type) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -38,6 +38,7 @@ import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -163,7 +163,7 @@ public class FileIncludeIndex extends FileBasedIndexExtension<FileIncludeIndex.K
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
interface Key {
|
||||
|
||||
@@ -18,6 +18,8 @@ package com.intellij.psi.impl.include;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Dmitry Avdeev
|
||||
*/
|
||||
@@ -26,7 +28,7 @@ class FileIncludeInfoImpl extends FileIncludeInfo {
|
||||
public final String providerId;
|
||||
|
||||
public FileIncludeInfoImpl(@NotNull String path, int offset, boolean runtimeOnly, String providerId) {
|
||||
super("", path, offset, runtimeOnly);
|
||||
super(new File(path).getName(), path, offset, runtimeOnly);
|
||||
this.providerId = providerId;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.intellij.psi.impl.include;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileWithId;
|
||||
@@ -34,12 +35,11 @@ import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.ParameterizedCachedValue;
|
||||
import com.intellij.psi.util.ParameterizedCachedValueProvider;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Dmitry Avdeev
|
||||
@@ -54,46 +54,68 @@ public class FileIncludeManagerImpl extends FileIncludeManager {
|
||||
|
||||
private final IncludeCacheHolder myIncludedHolder = new IncludeCacheHolder("compile time includes", "runtime includes") {
|
||||
@Override
|
||||
protected VirtualFile[] computeFiles(PsiFile file, boolean compileTimeOnly) {
|
||||
GlobalSearchScope scope = GlobalSearchScope.allScope(myProject);
|
||||
List<FileIncludeInfoImpl> infoList = FileIncludeIndex.getIncludes(file.getVirtualFile(), scope);
|
||||
ArrayList<VirtualFile> files = new ArrayList<VirtualFile>();
|
||||
for (FileIncludeInfoImpl info : infoList) {
|
||||
if (compileTimeOnly && info.runtimeOnly) {
|
||||
continue;
|
||||
}
|
||||
FileIncludeProvider includeProvider = myProviderMap.get(info.providerId);
|
||||
if (includeProvider != null) {
|
||||
PsiFileSystemItem virtualFile = includeProvider.resolveInclude(info, file, myProject);
|
||||
if (virtualFile != null) {
|
||||
files.add(virtualFile.getVirtualFile());
|
||||
protected VirtualFile[] computeFiles(final PsiFile file, final boolean compileTimeOnly) {
|
||||
final ArrayList<VirtualFile> files = new ArrayList<VirtualFile>();
|
||||
processIncludes(file, new Processor<FileIncludeInfo>() {
|
||||
@Override
|
||||
public boolean process(FileIncludeInfo info) {
|
||||
if (compileTimeOnly != info.runtimeOnly) {
|
||||
PsiFileSystemItem virtualFile = resolveFileInclude(info, file);
|
||||
if (virtualFile != null) {
|
||||
files.add(virtualFile.getVirtualFile());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
});
|
||||
return files.toArray(new VirtualFile[files.size()]);
|
||||
}
|
||||
};
|
||||
|
||||
public void processIncludes(PsiFile file, Processor<FileIncludeInfo> processor) {
|
||||
GlobalSearchScope scope = GlobalSearchScope.allScope(myProject);
|
||||
List<FileIncludeInfoImpl> infoList = FileIncludeIndex.getIncludes(file.getVirtualFile(), scope);
|
||||
for (FileIncludeInfoImpl info : infoList) {
|
||||
if (!processor.process(info)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final IncludeCacheHolder myIncludingHolder = new IncludeCacheHolder("compile time contexts", "runtime contexts") {
|
||||
@Override
|
||||
protected VirtualFile[] computeFiles(PsiFile context, boolean compileTimeOnly) {
|
||||
final ArrayList<VirtualFile> files = new ArrayList<VirtualFile>();
|
||||
processIncludingFiles(context, new Processor<Pair<VirtualFile, FileIncludeInfo>>() {
|
||||
@Override
|
||||
public boolean process(Pair<VirtualFile, FileIncludeInfo> virtualFileFileIncludeInfoPair) {
|
||||
files.add(virtualFileFileIncludeInfoPair.first);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return VfsUtil.toVirtualFileArray(files);
|
||||
}
|
||||
};
|
||||
|
||||
private final IncludeCacheHolder myIncludingHolder = new IncludeCacheHolder("compile time contexts", "runtime contexts") {
|
||||
@Override
|
||||
protected VirtualFile[] computeFiles(PsiFile file, boolean compileTimeOnly) {
|
||||
MultiMap<VirtualFile,FileIncludeInfoImpl> infoList = FileIncludeIndex.getIncludingFileCandidates(file.getName(), GlobalSearchScope.allScope(myProject));
|
||||
ArrayList<VirtualFile> files = new ArrayList<VirtualFile>();
|
||||
for (VirtualFile candidate : infoList.keySet()) {
|
||||
PsiFile psiFile = myPsiManager.findFile(candidate);
|
||||
if (psiFile == null) continue;
|
||||
for (FileIncludeInfoImpl info : infoList.get(candidate)) {
|
||||
FileIncludeProvider includeProvider = myProviderMap.get(info.providerId);
|
||||
if (includeProvider != null) {
|
||||
if (file.equals(includeProvider.resolveInclude(info, psiFile, myProject))) {
|
||||
files.add(candidate);
|
||||
}
|
||||
public void processIncludingFiles(PsiFile context, Processor<Pair<VirtualFile, FileIncludeInfo>> processor) {
|
||||
context = context.getOriginalFile();
|
||||
VirtualFile contextFile = context.getVirtualFile();
|
||||
if (contextFile == null) return;
|
||||
MultiMap<VirtualFile,FileIncludeInfoImpl> infoList = FileIncludeIndex.getIncludingFileCandidates(context.getName(), GlobalSearchScope.allScope(myProject));
|
||||
for (VirtualFile candidate : infoList.keySet()) {
|
||||
PsiFile psiFile = myPsiManager.findFile(candidate);
|
||||
if (psiFile == null || context.equals(psiFile)) continue;
|
||||
for (FileIncludeInfo info : infoList.get(candidate)) {
|
||||
PsiFileSystemItem item = resolveFileInclude(info, psiFile);
|
||||
if (item != null && contextFile.equals(item.getVirtualFile())) {
|
||||
if (!processor.process(Pair.create(candidate, info))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
return VfsUtil.toVirtualFileArray(files);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public FileIncludeManagerImpl(Project project, PsiManager psiManager, PsiFileFactory psiFileFactory,
|
||||
CachedValuesManager cachedValuesManager) {
|
||||
@@ -120,19 +142,23 @@ public class FileIncludeManagerImpl extends FileIncludeManager {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public VirtualFile[] getIncludingFiles(VirtualFile file, boolean compileTimeOnly) {
|
||||
return myIncludingHolder.getAllFiles(file, compileTimeOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiFileSystemItem resolveFileReference(String text, PsiFile context) {
|
||||
|
||||
PsiFileImpl psiFile = (PsiFileImpl)myPsiFileFactory.createFileFromText("dummy.txt", text);
|
||||
public PsiFileSystemItem resolveFileInclude(FileIncludeInfo info, PsiFile context) {
|
||||
|
||||
PsiFileImpl psiFile = (PsiFileImpl)myPsiFileFactory.createFileFromText("dummy.txt", info.path);
|
||||
psiFile.setOriginalFile(context);
|
||||
|
||||
return new FileReferenceSet(psiFile).resolve();
|
||||
return new FileReferenceSet(psiFile) {
|
||||
@Override
|
||||
protected boolean useIncludingFileAsContext() {
|
||||
return false;
|
||||
}
|
||||
}.resolve();
|
||||
}
|
||||
|
||||
private abstract class IncludeCacheHolder {
|
||||
@@ -140,14 +166,14 @@ public class FileIncludeManagerImpl extends FileIncludeManager {
|
||||
private final Key<ParameterizedCachedValue<VirtualFile[], PsiFile>> COMPILE_TIME_KEY;
|
||||
private final Key<ParameterizedCachedValue<VirtualFile[], PsiFile>> RUNTIME_KEY;
|
||||
|
||||
private final ParameterizedCachedValueProvider<VirtualFile[], PsiFile> COMPILE_TIME_PROVIDER = new IncludedFilesProvider(false) {
|
||||
private final ParameterizedCachedValueProvider<VirtualFile[], PsiFile> COMPILE_TIME_PROVIDER = new IncludedFilesProvider(true) {
|
||||
@Override
|
||||
protected VirtualFile[] computeFiles(PsiFile file, boolean compileTimeOnly) {
|
||||
return IncludeCacheHolder.this.computeFiles(file, compileTimeOnly);
|
||||
}
|
||||
};
|
||||
|
||||
private final ParameterizedCachedValueProvider<VirtualFile[], PsiFile> RUNTIME_PROVIDER = new IncludedFilesProvider(true) {
|
||||
private final ParameterizedCachedValueProvider<VirtualFile[], PsiFile> RUNTIME_PROVIDER = new IncludedFilesProvider(false) {
|
||||
@Override
|
||||
protected VirtualFile[] computeFiles(PsiFile file, boolean compileTimeOnly) {
|
||||
return IncludeCacheHolder.this.computeFiles(file, compileTimeOnly);
|
||||
@@ -160,36 +186,20 @@ public class FileIncludeManagerImpl extends FileIncludeManager {
|
||||
}
|
||||
|
||||
public VirtualFile[] getAllFiles(VirtualFile file, boolean compileTimeOnly) {
|
||||
ArrayList<VirtualFile[]> result = new ArrayList<VirtualFile[]>();
|
||||
Set<VirtualFile> result = new HashSet<VirtualFile>();
|
||||
getFilesRecursively(file, compileTimeOnly, result);
|
||||
switch (result.size()) {
|
||||
case 0:
|
||||
return VirtualFile.EMPTY_ARRAY;
|
||||
case 1:
|
||||
return result.get(0);
|
||||
default:
|
||||
int size = 0;
|
||||
for (VirtualFile[] files : result) {
|
||||
size+=files.length;
|
||||
}
|
||||
VirtualFile[] files = new VirtualFile[size];
|
||||
int pos = 0;
|
||||
for (VirtualFile[] virtualFiles : result) {
|
||||
System.arraycopy(virtualFiles, 0, files, pos, virtualFiles.length);
|
||||
pos += virtualFiles.length;
|
||||
}
|
||||
return files;
|
||||
}
|
||||
return result.toArray(new VirtualFile[result.size()]);
|
||||
}
|
||||
|
||||
private void getFilesRecursively(VirtualFile file, boolean compileTimeOnly, List<VirtualFile[]> result) {
|
||||
private void getFilesRecursively(VirtualFile file, boolean compileTimeOnly, Set<VirtualFile> result) {
|
||||
if (result.contains(file)) return;
|
||||
PsiFile psiFile = myPsiManager.findFile(file);
|
||||
if (psiFile == null) return;
|
||||
VirtualFile[] includes = compileTimeOnly
|
||||
? myCachedValuesManager.getParameterizedCachedValue(psiFile, COMPILE_TIME_KEY, COMPILE_TIME_PROVIDER, false, psiFile)
|
||||
: myCachedValuesManager.getParameterizedCachedValue(psiFile, RUNTIME_KEY, RUNTIME_PROVIDER, false, psiFile);
|
||||
if (includes.length != 0) {
|
||||
result.add(includes);
|
||||
result.addAll(Arrays.asList(includes));
|
||||
for (VirtualFile include : includes) {
|
||||
getFilesRecursively(include, compileTimeOnly, result);
|
||||
}
|
||||
|
||||
@@ -17,13 +17,9 @@
|
||||
package com.intellij.psi.impl.include;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiFileSystemItem;
|
||||
import com.intellij.util.indexing.FileContent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Dmitry Avdeev
|
||||
@@ -39,9 +35,4 @@ public abstract class FileIncludeProvider {
|
||||
|
||||
@NotNull
|
||||
public abstract FileIncludeInfo[] getIncludeInfos(FileContent content);
|
||||
|
||||
@Nullable
|
||||
public PsiFileSystemItem resolveInclude(FileIncludeInfo include, PsiFile context, Project project) {
|
||||
return FileIncludeManager.getManager(project).resolveFileReference(include.path, context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
|
||||
protected PsiFile myOriginalFile = null;
|
||||
private final FileViewProvider myViewProvider;
|
||||
private static final Key<Document> HARD_REFERENCE_TO_DOCUMENT = new Key<Document>("HARD_REFERENCE_TO_DOCUMENT");
|
||||
private final Object myStubLock = new String("file's stub lock");
|
||||
private final Object myStubLock = new Object();
|
||||
private SoftReference<StubTree> myStub;
|
||||
protected final PsiManagerEx myManager;
|
||||
private volatile Object myTreeElementPointer; // SoftReference/WeakReference to RepositoryTreeElement when has repository id, RepositoryTreeElement otherwise
|
||||
|
||||
+2
-18
@@ -22,15 +22,10 @@ import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.util.Function;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -46,7 +41,6 @@ public class FileReferenceSet {
|
||||
private static final FileType[] EMPTY_FILE_TYPES = {};
|
||||
private static final char SEPARATOR = '/';
|
||||
private static final String SEPARATOR_STRING = "/";
|
||||
private static final Key<CachedValue<Collection<PsiFileSystemItem>>> DEFAULT_CONTEXTS_KEY = new Key<CachedValue<Collection<PsiFileSystemItem>>>("default file contexts");
|
||||
public static final CustomizableReferenceProvider.CustomizationKey<Function<PsiFile, Collection<PsiFileSystemItem>>> DEFAULT_PATH_EVALUATOR_OPTION =
|
||||
new CustomizableReferenceProvider.CustomizationKey<Function<PsiFile, Collection<PsiFileSystemItem>>>(PsiBundle.message("default.path.evaluator.option"));
|
||||
public static final Function<PsiFile, Collection<PsiFileSystemItem>> ABSOLUTE_TOP_LEVEL = new Function<PsiFile, Collection<PsiFileSystemItem>>() {
|
||||
@@ -262,17 +256,7 @@ public class FileReferenceSet {
|
||||
return getAbsoluteTopLevelDirLocations(file);
|
||||
}
|
||||
|
||||
final CachedValueProvider<Collection<PsiFileSystemItem>> myDefaultContextProvider = new CachedValueProvider<Collection<PsiFileSystemItem>>() {
|
||||
public Result<Collection<PsiFileSystemItem>> compute() {
|
||||
final Collection<PsiFileSystemItem> contexts = getContextByFile(file);
|
||||
return Result.createSingleDependency(contexts,
|
||||
PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
|
||||
}
|
||||
};
|
||||
final CachedValuesManager cachedValuesManager = CachedValuesManager.getManager(myElement.getProject());
|
||||
final Collection<PsiFileSystemItem> value =
|
||||
cachedValuesManager.getCachedValue(file, DEFAULT_CONTEXTS_KEY, myDefaultContextProvider, false);
|
||||
return value == null ? Collections.<PsiFileSystemItem>emptyList() : value;
|
||||
return getContextByFile(file);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -285,7 +269,7 @@ public class FileReferenceSet {
|
||||
return file.getOriginalFile();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
private Collection<PsiFileSystemItem> getContextByFile(@NotNull PsiFile file) {
|
||||
final PsiElement context = file.getContext();
|
||||
if (context != null) file = context.getContainingFile();
|
||||
|
||||
@@ -70,6 +70,10 @@ public interface StatusBar extends StatusBarInfo {
|
||||
@Deprecated
|
||||
void addCustomIndicationComponent(@NotNull JComponent c);
|
||||
|
||||
/**
|
||||
* @deprecated use removeWidget instead
|
||||
*/
|
||||
@Deprecated
|
||||
void removeCustomIndicationComponent(@NotNull JComponent c);
|
||||
|
||||
void removeWidget(@NotNull String id);
|
||||
|
||||
@@ -33,7 +33,7 @@ import java.awt.event.MouseEvent;
|
||||
*/
|
||||
public interface StatusBarWidget extends Disposable {
|
||||
|
||||
enum Type {
|
||||
enum PlatformType {
|
||||
DEFAULT, MAC
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ public interface StatusBarWidget extends Disposable {
|
||||
String ID();
|
||||
|
||||
@Nullable
|
||||
WidgetPresentation getPresentation(@NotNull Type type);
|
||||
WidgetPresentation getPresentation(@NotNull PlatformType type);
|
||||
|
||||
void install(@NotNull final StatusBar statusBar);
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ public class IdeMessagePanel extends JPanel implements MessagePoolListener, Cust
|
||||
return "FatalError";
|
||||
}
|
||||
|
||||
public WidgetPresentation getPresentation(@NotNull Type type) {
|
||||
public WidgetPresentation getPresentation(@NotNull PlatformType type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ public class IdeNotificationArea implements StatusBarWidget, StatusBarWidget.Ico
|
||||
public IdeNotificationArea() {
|
||||
}
|
||||
|
||||
public WidgetPresentation getPresentation(@NotNull Type type) {
|
||||
public WidgetPresentation getPresentation(@NotNull PlatformType type) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,9 @@ public class DuplicateAction extends EditorAction {
|
||||
VisualPosition caret = editor.getCaretModel().getVisualPosition();
|
||||
LogicalPosition lineStart = editor.visualToLogicalPosition(new VisualPosition(caret.line, 0));
|
||||
LogicalPosition nextLineStart = editor.visualToLogicalPosition(new VisualPosition(caret.line + 1, 0));
|
||||
if (nextLineStart.line == lineStart.line) {
|
||||
nextLineStart = new LogicalPosition(lineStart.line+1, 0);
|
||||
}
|
||||
|
||||
int start = editor.logicalPositionToOffset(lineStart);
|
||||
int end = editor.logicalPositionToOffset(nextLineStart);
|
||||
@@ -86,4 +89,4 @@ public class DuplicateAction extends EditorAction {
|
||||
presentation.setText(EditorBundle.message("action.duplicate.line"), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@ import com.intellij.ide.DeleteProvider;
|
||||
import com.intellij.ide.PasteProvider;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.FoldingModel;
|
||||
import com.intellij.openapi.editor.LogicalPosition;
|
||||
import com.intellij.openapi.editor.VisualPosition;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
|
||||
import com.intellij.openapi.editor.impl.TextDrawingCallback;
|
||||
@@ -124,4 +127,13 @@ public interface EditorEx extends Editor {
|
||||
int calcColumnNumber(int offset, int lineIndex);
|
||||
|
||||
TextDrawingCallback getTextDrawingCallback();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
FoldingModelEx getFoldingModel();
|
||||
|
||||
@NotNull
|
||||
LogicalPosition visualToLogicalPosition(@NotNull VisualPosition visiblePos, boolean softWrapAware);
|
||||
|
||||
@NotNull LogicalPosition offsetToLogicalPosition(int offset, boolean softWrapAware);
|
||||
}
|
||||
|
||||
@@ -35,26 +35,22 @@ import java.util.List;
|
||||
public interface SoftWrapModelEx extends SoftWrapModel {
|
||||
|
||||
/**
|
||||
* Asks current model to adjust logical position for the given visual position if necessary.
|
||||
* <p/>
|
||||
* Given logical position is allowed to be non-soft wrap aware, i.e. the one calculated as there are no soft wraps at the moment.
|
||||
* Asks current model to map given visual position to logical.
|
||||
*
|
||||
* @param defaultLogical default logical position that corresponds to the given visual position
|
||||
* @param visual target visual position for which logical position should be adjusted if necessary
|
||||
* @param visual target visual position for which logical position should be mapped
|
||||
* @return logical position that corresponds to the given visual position
|
||||
*/
|
||||
@NotNull
|
||||
LogicalPosition adjustLogicalPosition(@NotNull LogicalPosition defaultLogical, @NotNull VisualPosition visual);
|
||||
LogicalPosition visualToLogicalPosition(@NotNull VisualPosition visual);
|
||||
|
||||
/**
|
||||
* Asks current model to adjust logical position for the given document offset.
|
||||
* Asks current model to map given document offset to logical position.
|
||||
*
|
||||
* @param defaultLogical default logical position that corresponds to the given document offset
|
||||
* @param offset target editor document offset
|
||||
* @return logical position for the given editor document offset
|
||||
*/
|
||||
@NotNull
|
||||
LogicalPosition adjustLogicalPosition(LogicalPosition defaultLogical, int offset);
|
||||
LogicalPosition offsetToLogicalPosition(int offset);
|
||||
|
||||
/**
|
||||
* Asks current model to adjust visual position that corresponds to the given logical position if necessary.
|
||||
@@ -103,7 +99,15 @@ public interface SoftWrapModelEx extends SoftWrapModel {
|
||||
* @param drawingType target drawing type
|
||||
* @return width in pixels required for the painting of the given type
|
||||
*/
|
||||
int getMinDrawingWidth(@NotNull SoftWrapDrawingType drawingType);
|
||||
int getMinDrawingWidthInPixels(@NotNull SoftWrapDrawingType drawingType);
|
||||
|
||||
/**
|
||||
* Allows to ask for the minimal width in columns required for painting of the given type.
|
||||
*
|
||||
* @param drawingType target drawing type
|
||||
* @return width in columns required for the painting of the given type
|
||||
*/
|
||||
int getMinDrawingWidthInColumns(@NotNull SoftWrapDrawingType drawingType);
|
||||
|
||||
/**
|
||||
* Registers given listener within the current model
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class EditorUtil {
|
||||
private EditorUtil() { }
|
||||
@@ -178,54 +179,69 @@ public class EditorUtil {
|
||||
*/
|
||||
public static int calcOffset(Editor editor, CharSequence text, int start, int end, int columnNumber, int tabSize) {
|
||||
final int maxScanIndex = Math.min(start + columnNumber + 1, end);
|
||||
if (editor == null) {
|
||||
return calcSoftWrapUnawareOffset(text, start, maxScanIndex, columnNumber, tabSize);
|
||||
}
|
||||
|
||||
EditorEx editorImpl = (EditorEx)editor;
|
||||
int offset = start;
|
||||
IterationState state = new IterationState(editorImpl, offset, false);
|
||||
int fontType = state.getMergedAttributes().getFontType();
|
||||
int column = 0;
|
||||
int x = 0;
|
||||
int spaceSize = getSpaceWidth(fontType, editorImpl);
|
||||
SoftWrapModel softWrapModel = editor.getSoftWrapModel();
|
||||
while (column < columnNumber) {
|
||||
TextChange softWrap = softWrapModel.getSoftWrap(offset);
|
||||
if (softWrap != null) {
|
||||
x = softWrapModel.getSoftWrapIndentWidthInPixels(softWrap);
|
||||
List<? extends TextChange> softWraps = softWrapModel.getSoftWrapsForRange(start, maxScanIndex);
|
||||
int startToUse = start;
|
||||
int x = 0;
|
||||
AtomicInteger currentColumn = new AtomicInteger();
|
||||
for (TextChange softWrap : softWraps) {
|
||||
// There is a possible case that target column points inside soft wrap-introduced virtual space.
|
||||
if (currentColumn.get() >= columnNumber) {
|
||||
return startToUse;
|
||||
}
|
||||
if (offset >= state.getEndOffset()) {
|
||||
state.advance();
|
||||
fontType = state.getMergedAttributes().getFontType();
|
||||
int result = calcSoftWrapUnawareOffset(editor, text, startToUse, softWrap.getEnd(), columnNumber, tabSize, x, currentColumn);
|
||||
if (result >= 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
char c = offset < end ? text.charAt(offset++) : ' ';
|
||||
int prevX = x;
|
||||
if (c == '\t') {
|
||||
x = nextTabStop(x, editorImpl);
|
||||
}
|
||||
else {
|
||||
x += charWidth(c, fontType, editorImpl);
|
||||
}
|
||||
column += columnsNumber(c, x, prevX, spaceSize);
|
||||
startToUse = softWrap.getStart();
|
||||
x = softWrapModel.getSoftWrapIndentWidthInPixels(softWrap);
|
||||
}
|
||||
//if (column == columnNumber && offset < end && text.charAt(offset) == '\t' && (nextTabStop(x, editorImpl) - x) / spaceSize == 0) {
|
||||
// offset++;
|
||||
//}
|
||||
if (column > columnNumber) offset--;
|
||||
|
||||
return offset;
|
||||
// There is a possible case that target column points inside soft wrap-introduced virtual space.
|
||||
if (currentColumn.get() >= columnNumber) {
|
||||
return startToUse;
|
||||
}
|
||||
|
||||
int result = calcSoftWrapUnawareOffset(editor, text, startToUse, end, columnNumber, tabSize, x, currentColumn);
|
||||
if (result >= 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// We assume that given column points to the virtual space after the line end if control flow reaches this place,
|
||||
// hence, just return end of line offset then.
|
||||
return end;
|
||||
}
|
||||
|
||||
private static int calcSoftWrapUnawareOffset(CharSequence text, int start, int end, int columnNumber, int tabSize) {
|
||||
/**
|
||||
* Tries to match given logical column to the document offset assuming that it's located at <code>[start; end)</code> region.
|
||||
*
|
||||
* @param editor editor that is used to represent target document
|
||||
* @param text target document text
|
||||
* @param start start offset to check (inclusive)
|
||||
* @param end end offset to check (exclusive)
|
||||
* @param columnNumber target logical column number
|
||||
* @param tabSize user-defined desired number of columns to use for tabulation symbol representation
|
||||
* @param x <code>'x'</code> coordinate that corresponds to the given <code>'start'</code> offset
|
||||
* @param currentColumn logical column that corresponds to the given <code>'start'</code> offset
|
||||
* @return target offset that belongs to the <code>[start; end)</code> range and points to the target logical
|
||||
* column if any; <code>-1</code> otherwise
|
||||
*/
|
||||
private static int calcSoftWrapUnawareOffset(Editor editor, CharSequence text, int start, int end, int columnNumber, int tabSize, int x,
|
||||
AtomicInteger currentColumn)
|
||||
{
|
||||
// The main problem in a calculation is that target text may contain tabulation symbols and every such symbol may take different
|
||||
// number of logical columns to represent. E.g. it takes two columns if tab size is four and current column is two; three columns
|
||||
// if tab size is four and current column is one etc. So, first of all we check if there are tabulation symbols at the target
|
||||
// text fragment.
|
||||
boolean useOptimization = true;
|
||||
boolean hasNonTabs = false;
|
||||
boolean hasTabs = false;
|
||||
|
||||
for (int i = start; i < end; i++) {
|
||||
if (text.charAt(i) == '\t') {
|
||||
hasTabs = true;
|
||||
if (hasNonTabs) {
|
||||
useOptimization = false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -233,20 +249,79 @@ public class EditorUtil {
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasTabs) return Math.min(start + columnNumber, end);
|
||||
// Perform optimized processing if possible. 'Optimized' here means the processing when we exactly know how many logical
|
||||
// columns are occupied by tabulation symbols.
|
||||
if (editor == null || useOptimization) {
|
||||
if (!hasTabs) {
|
||||
int result = start + columnNumber - currentColumn.get();
|
||||
if (result < end) {
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
currentColumn.addAndGet(end - start);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int shift = 0;
|
||||
int offset = start;
|
||||
for (; offset < end && offset + shift < start + columnNumber; offset++) {
|
||||
if (text.charAt(offset) == '\t') {
|
||||
shift += getTabLength(offset + shift - start, tabSize) - 1;
|
||||
// This variable holds number of 'virtual' tab-introduced columns, e.g. there is a possible case that particular tab owns
|
||||
// three columns, hence, it increases 'shift' by two (3 - 1).
|
||||
int shift = 0;
|
||||
int offset = start;
|
||||
int prevX = x;
|
||||
for (; offset < end && offset + shift + currentColumn.get() < start + columnNumber; offset++) {
|
||||
if (text.charAt(offset) == '\t') {
|
||||
int nextX = nextTabStop(prevX, editor, tabSize);
|
||||
shift += columnsNumber(nextX - prevX, getSpaceWidth(Font.PLAIN, editor)) - 1;
|
||||
prevX = nextX;
|
||||
}
|
||||
}
|
||||
int diff = start + columnNumber - offset - shift - currentColumn.get();
|
||||
if (diff < 0) {
|
||||
return offset - 1;
|
||||
}
|
||||
else if (diff == 0) {
|
||||
return offset;
|
||||
}
|
||||
else {
|
||||
currentColumn.addAndGet(offset - start + shift);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (offset + shift > start + columnNumber) {
|
||||
offset--;
|
||||
|
||||
// It means that there are tabulation symbols that can't be explicitly mapped to the occupied logical columns number,
|
||||
// hence, we need to perform special calculations to get know that.
|
||||
EditorEx editorImpl = (EditorEx)editor;
|
||||
int offset = start;
|
||||
IterationState state = new IterationState(editorImpl, offset, false);
|
||||
int fontType = state.getMergedAttributes().getFontType();
|
||||
int column = currentColumn.get();
|
||||
int spaceSize = getSpaceWidth(fontType, editorImpl);
|
||||
for (; column < columnNumber && offset < end; offset++) {
|
||||
if (offset >= state.getEndOffset()) {
|
||||
state.advance();
|
||||
fontType = state.getMergedAttributes().getFontType();
|
||||
}
|
||||
|
||||
char c = text.charAt(offset);
|
||||
if (c == '\t') {
|
||||
int prevX = x;
|
||||
x = nextTabStop(x, editorImpl);
|
||||
column += columnsNumber(x - prevX, spaceSize);
|
||||
}
|
||||
else {
|
||||
x += charWidth(c, fontType, editorImpl);
|
||||
column++;
|
||||
}
|
||||
}
|
||||
|
||||
return offset;
|
||||
if (column == columnNumber) {
|
||||
return offset;
|
||||
}
|
||||
if (column > columnNumber && text.charAt(offset) == '\t') {
|
||||
return offset - 1;
|
||||
}
|
||||
currentColumn.set(column);
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static int getTabLength(int colNumber, int tabSize) {
|
||||
@@ -328,7 +403,13 @@ public class EditorUtil {
|
||||
if (tabSize <= 0) {
|
||||
tabSize = 1;
|
||||
}
|
||||
return nextTabStop(x, editor, tabSize);
|
||||
}
|
||||
|
||||
public static int nextTabStop(int x, Editor editor, int tabSize) {
|
||||
if (tabSize <= 0) {
|
||||
return x + getSpaceWidth(Font.PLAIN, editor);
|
||||
}
|
||||
tabSize *= getSpaceWidth(Font.PLAIN, editor);
|
||||
|
||||
int nTabs = x / tabSize;
|
||||
@@ -371,6 +452,21 @@ public class EditorUtil {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to answer how many visual columns are occupied by the given width.
|
||||
*
|
||||
* @param width target width
|
||||
* @param spaceSize width of the single space symbol within the target editor
|
||||
* @return number of visual columns are occupied by the given width
|
||||
*/
|
||||
public static int columnsNumber(int width, int spaceSize) {
|
||||
int result = width / spaceSize;
|
||||
if (width % spaceSize > 0) {
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to answer what width in pixels is required to draw fragment of the given char array from <code>[start; end)</code> interval
|
||||
* at the given editor.
|
||||
@@ -390,10 +486,10 @@ public class EditorUtil {
|
||||
* from <code>[1; tab size]</code> (check {@link #nextTabStop(int, Editor)} for more details)
|
||||
* @return width in pixels required for target text representation
|
||||
*/
|
||||
public static int textWidth(@NotNull Editor editor, char[] text, int start, int end, int fontType, int x) {
|
||||
public static int textWidth(@NotNull Editor editor, CharSequence text, int start, int end, int fontType, int x) {
|
||||
int result = 0;
|
||||
for (int i = start; i < end; i++) {
|
||||
char c = text[i];
|
||||
char c = text.charAt(i);
|
||||
if (c != '\t') {
|
||||
FontInfo font = fontForChar(c, fontType, editor);
|
||||
result += font.charWidth(c, editor.getContentComponent());
|
||||
|
||||
@@ -470,24 +470,27 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener {
|
||||
|
||||
private VerticalInfo createVerticalInfo(LogicalPosition position) {
|
||||
Document document = myEditor.getDocument();
|
||||
int line = position.line;
|
||||
int logicalLine = position.line;
|
||||
|
||||
// There is a possible case that active logical line is represented on multiple lines due to soft wraps processing.
|
||||
// We want to highlight those visual lines as 'active' then, so, we calculate 'y' position for the logical line start
|
||||
// and height in accordance with the number of occupied visual lines.
|
||||
int y = myEditor.logicalPositionToXY(myEditor.offsetToLogicalPosition(document.getLineStartOffset(line))).y;
|
||||
LogicalPosition logicalPosition = myEditor.offsetToLogicalPosition(document.getLineStartOffset(logicalLine));
|
||||
VisualPosition visualPosition = myEditor.logicalToVisualPosition(logicalPosition);
|
||||
int y = myEditor.visualPositionToXY(visualPosition).y;
|
||||
int height = myEditor.getLineHeight();
|
||||
if (line < document.getLineCount() - 1) {
|
||||
int nextLineY = myEditor.logicalPositionToXY(myEditor.offsetToLogicalPosition(document.getLineStartOffset(line + 1))).y;
|
||||
int heightCandidate = nextLineY - y;
|
||||
|
||||
// There is a possible case that active line is the one that ends with folding, so, 'y' position
|
||||
// of its next logical line is the same as the previous. We explicitly check that in order to use non-standard
|
||||
// line height only in case of visible soft-wrapped line.
|
||||
if (heightCandidate > height) {
|
||||
height = heightCandidate;
|
||||
int visualLine = visualPosition.line + 1;
|
||||
int lastVisualLine = myEditor.offsetToVisualPosition(document.getTextLength() - 1).line;
|
||||
for (; visualLine <= lastVisualLine; visualLine++) {
|
||||
LogicalPosition logical = myEditor.visualToLogicalPosition(new VisualPosition(visualLine, 0));
|
||||
if (logical.line == logicalLine) {
|
||||
height += myEditor.getLineHeight();
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new VerticalInfo(y, height);
|
||||
}
|
||||
|
||||
|
||||
+11
-8
@@ -17,6 +17,9 @@ package com.intellij.openapi.editor.impl;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ex.util.EditorUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
@@ -31,17 +34,17 @@ public class DefaultEditorTextRepresentationHelper implements EditorTextRepresen
|
||||
}
|
||||
|
||||
@Override
|
||||
public int toVisualColumnSymbolsNumber(CharSequence text, int start, int end, int x) {
|
||||
public int toVisualColumnSymbolsNumber(@NotNull CharSequence text, int start, int end, int x) {
|
||||
return EditorUtil.textWidthInColumns(myEditor, text, start, end, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int charWidth(char c, int x, int fontType) {
|
||||
if (c == '\t') {
|
||||
return EditorUtil.nextTabStop(x, myEditor) - x;
|
||||
}
|
||||
else {
|
||||
return EditorUtil.charWidth(c, fontType, myEditor);
|
||||
}
|
||||
public int toVisualColumnSymbolsNumber(int width) {
|
||||
return EditorUtil.columnsNumber(width, EditorUtil.getSpaceWidth(Font.PLAIN, myEditor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int textWidth(@NotNull CharSequence text, int start, int end, int x) {
|
||||
return EditorUtil.textWidth(myEditor, text, start, end, Font.PLAIN, x);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +105,7 @@ import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public final class EditorImpl extends UserDataHolderBase implements EditorEx, HighlighterClient, Queryable {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.EditorImpl");
|
||||
@@ -122,7 +123,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
ComplementaryFontsRegistry registry; // load costly font info
|
||||
}
|
||||
|
||||
private final CommandProcessor myCommandProcessor;
|
||||
private final CommandProcessor myCommandProcessor;
|
||||
private final MyScrollBar myVerticalScrollBar;
|
||||
|
||||
private final CopyOnWriteArrayList<EditorMouseListener> myMouseListeners = ContainerUtil.createEmptyCOWList();
|
||||
@@ -440,7 +441,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FoldingModel getFoldingModel() {
|
||||
public FoldingModelEx getFoldingModel() {
|
||||
return myFoldingModel;
|
||||
}
|
||||
|
||||
@@ -902,7 +903,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
|
||||
// Process 'after soft wrap' sign.
|
||||
prevX = x;
|
||||
charWidth = mySoftWrapModel.getMinDrawingWidth(SoftWrapDrawingType.AFTER_SOFT_WRAP);
|
||||
charWidth = mySoftWrapModel.getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP);
|
||||
x += charWidth;
|
||||
if (x >= px) {
|
||||
break outer;
|
||||
@@ -983,16 +984,15 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
return offsetToLogicalPosition(offset, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public LogicalPosition offsetToLogicalPosition(int offset, boolean softWrapAware) {
|
||||
if (softWrapAware) {
|
||||
return mySoftWrapModel.offsetToLogicalPosition(offset);
|
||||
}
|
||||
int line = calcLogicalLineNumber(offset, false);
|
||||
int column = calcColumnNumber(offset, line, false);
|
||||
LogicalPosition position = new LogicalPosition(line, column);
|
||||
if (softWrapAware) {
|
||||
return mySoftWrapModel.adjustLogicalPosition(position, offset);
|
||||
}
|
||||
else {
|
||||
return position;
|
||||
}
|
||||
return new LogicalPosition(line, column);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -1055,7 +1055,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
if (i >= 0) {
|
||||
start = i + 1;
|
||||
}
|
||||
return new Point(EditorUtil.textWidth(this, softWrapChars, start, column + 1, Font.PLAIN, 0), y);
|
||||
return new Point(EditorUtil.textWidth(this, softWrap.getText(), start, column + 1, Font.PLAIN, 0), y);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1749,7 +1749,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
|
||||
if (backColor != null && !backColor.equals(defaultBackground) && clip.intersects(position.x, position.y, w, getLineHeight())) {
|
||||
if (backColor.equals(myLastBackgroundColor) && myLastBackgroundPosition.y == position.y &&
|
||||
myLastBackgroundPosition.x + myLastBackgroundWidth == position.x) {
|
||||
myLastBackgroundPosition.x + myLastBackgroundWidth == position.x) {
|
||||
myLastBackgroundWidth += w;
|
||||
}
|
||||
else {
|
||||
@@ -1794,8 +1794,14 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
|
||||
int visibleLineNumber = clip.y / lineHeight;
|
||||
|
||||
LogicalPosition logicalPosition = xyToLogicalPosition(new Point(0, clip.y));
|
||||
int startLineNumber = logicalPosition.line;
|
||||
// We use AtomicReference here just as a holder for LogicalPosition
|
||||
// The main idea is that there is a possible case that we need to perform painting starting from soft-wrapped logical line.
|
||||
// We may want to skip necessary of visual lines then. Hence, we remember logical position that corresponds to the starting
|
||||
// visual line in order to use it for further processing. As soon as necessary number of visual lines is skipped, logical
|
||||
// position is expected to be set to null as an indication that no soft wrap-introduced visual lines should be skipped on
|
||||
// current painting iteration.
|
||||
AtomicReference<LogicalPosition> logicalPosition = new AtomicReference<LogicalPosition>(xyToLogicalPosition(new Point(0, clip.y)));
|
||||
int startLineNumber = logicalPosition.get().line;
|
||||
|
||||
Point position = new Point(0, visibleLineNumber * lineHeight);
|
||||
if (startLineNumber == 0 && myPrefixText != null) {
|
||||
@@ -1850,10 +1856,19 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
else {
|
||||
FoldRegion collapsedFolderAt = iterationState.getCurrentFold();
|
||||
if (collapsedFolderAt != null) {
|
||||
TextChange softWrap = mySoftWrapModel.getSoftWrap(collapsedFolderAt.getStartOffset());
|
||||
if (softWrap != null && logicalPosition.get() != null) {
|
||||
position.x = drawStringWithSoftWraps(
|
||||
g, chars, collapsedFolderAt.getStartOffset(), collapsedFolderAt.getStartOffset(), position, clip, effectColor, effectType,
|
||||
fontType, currentColor, logicalPosition
|
||||
);
|
||||
}
|
||||
int foldingXStart = position.x;
|
||||
position.x =
|
||||
drawStringWithSoftWraps(g, collapsedFolderAt.getPlaceholderText(), position, clip, effectColor, effectType,
|
||||
fontType, currentColor, logicalPosition);
|
||||
position.x = drawString(
|
||||
g, collapsedFolderAt.getPlaceholderText(), position, clip, effectColor, effectType, fontType, currentColor
|
||||
);
|
||||
//drawStringWithSoftWraps(g, collapsedFolderAt.getPlaceholderText(), position, clip, effectColor, effectType,
|
||||
// fontType, currentColor, logicalPosition);
|
||||
BorderEffect.paintFoldedEffect(g, foldingXStart, position.y, position.x, getLineHeight(), effectColor, effectType);
|
||||
|
||||
}
|
||||
@@ -1963,7 +1978,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
final int lastCount = count - 1;
|
||||
final Color lastColor = color[lastCount];
|
||||
if (_data == myLastData && _start == ends[lastCount] && (_color == null || lastColor == null || _color == lastColor)
|
||||
&& _y == y[lastCount] /* there is a possible case that vertical position is adjusted because of soft wrap */)
|
||||
&& _y == y[lastCount] /* there is a possible case that vertical position is adjusted because of soft wrap */)
|
||||
{
|
||||
ends[lastCount] = _end;
|
||||
if (lastColor == null) color[lastCount] = _color;
|
||||
@@ -1996,7 +2011,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
private void paintCaretCursor(Graphics g) {
|
||||
// There is a possible case that visual caret position is changed because of newly added or removed soft wraps.
|
||||
// We check if that's the case and ask caret model to recalculate visual position if necessary.
|
||||
|
||||
|
||||
myCaretCursor.paint(g);
|
||||
}
|
||||
|
||||
@@ -2046,7 +2061,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
EffectType effectType,
|
||||
int fontType,
|
||||
Color fontColor,
|
||||
LogicalPosition startDrawingLogicalPosition)
|
||||
AtomicReference<LogicalPosition> startDrawingLogicalPosition)
|
||||
{
|
||||
return drawStringWithSoftWraps(g, text.toCharArray(), 0, text.length(), position, clip, effectColor, effectType,
|
||||
fontType, fontColor, startDrawingLogicalPosition);
|
||||
@@ -2062,16 +2077,19 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
EffectType effectType,
|
||||
int fontType,
|
||||
Color fontColor,
|
||||
LogicalPosition startDrawingLogicalPosition)
|
||||
AtomicReference<LogicalPosition> startDrawingLogicalPosition)
|
||||
{
|
||||
int startToUse = start;
|
||||
|
||||
// There is a possible case that starting logical line is split by soft-wraps and it's part after the split should be drawn.
|
||||
// We need to skip necessary number of visual lines then.
|
||||
int softWrapLinesToSkip = startDrawingLogicalPosition.softWrapLinesOnCurrentLogicalLine;
|
||||
int softWrapLinesToSkip = 0;
|
||||
if (startDrawingLogicalPosition.get() != null) {
|
||||
softWrapLinesToSkip = startDrawingLogicalPosition.get().softWrapLinesOnCurrentLogicalLine;
|
||||
}
|
||||
TextChange lastSkippedSoftWrap = null;
|
||||
if (softWrapLinesToSkip > 0) {
|
||||
List<? extends TextChange> softWraps = getSoftWrapModel().getSoftWrapsForLine(startDrawingLogicalPosition.line);
|
||||
List<? extends TextChange> softWraps = getSoftWrapModel().getSoftWrapsForLine(startDrawingLogicalPosition.get().line);
|
||||
for (TextChange softWrap : softWraps) {
|
||||
softWrapLinesToSkip -= StringUtil.countNewLines(softWrap.getText());
|
||||
if (softWrapLinesToSkip <= 0) {
|
||||
@@ -2080,13 +2098,14 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
startToUse = Math.max(startToUse, start);
|
||||
|
||||
if (startToUse >= end) {
|
||||
return position.x;
|
||||
}
|
||||
startDrawingLogicalPosition.set(null);
|
||||
|
||||
outer:
|
||||
for (TextChange softWrap : getSoftWrapModel().getSoftWrapsForRange(startToUse, end)) {
|
||||
@@ -2667,10 +2686,16 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
|
||||
@NotNull
|
||||
public LogicalPosition visualToLogicalPosition(@NotNull VisualPosition visiblePos) {
|
||||
assertReadAccess();
|
||||
if (!myFoldingModel.isFoldingEnabled() && !mySoftWrapModel.isSoftWrappingEnabled()) {
|
||||
return new LogicalPosition(visiblePos.line, visiblePos.column);
|
||||
return visualToLogicalPosition(visiblePos, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public LogicalPosition visualToLogicalPosition(@NotNull VisualPosition visiblePos, boolean softWrapAware) {
|
||||
if (softWrapAware) {
|
||||
return mySoftWrapModel.visualToLogicalPosition(visiblePos);
|
||||
}
|
||||
assertReadAccess();
|
||||
if (!myFoldingModel.isFoldingEnabled()) return new LogicalPosition(visiblePos.line, visiblePos.column);
|
||||
|
||||
int line = visiblePos.line;
|
||||
int column = visiblePos.column;
|
||||
@@ -2678,35 +2703,23 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
FoldRegion lastCollapsedBefore = getLastCollapsedBeforePosition(visiblePos);
|
||||
|
||||
if (lastCollapsedBefore != null) {
|
||||
LogicalPosition softWrapAwareLogFoldEnd = offsetToLogicalPosition(lastCollapsedBefore.getEndOffset());
|
||||
VisualPosition softWrapAwareVisFoldEnd = logicalToVisualPosition(softWrapAwareLogFoldEnd);
|
||||
if (softWrapAwareVisFoldEnd.line == visiblePos.line) {
|
||||
if (visiblePos.column == softWrapAwareVisFoldEnd.column) {
|
||||
return softWrapAwareLogFoldEnd;
|
||||
}
|
||||
else if (visiblePos.column > softWrapAwareVisFoldEnd.column) {
|
||||
int columnToUse = softWrapAwareLogFoldEnd.column + visiblePos.column - softWrapAwareVisFoldEnd.column;
|
||||
return new LogicalPosition(
|
||||
softWrapAwareLogFoldEnd.line, columnToUse, softWrapAwareLogFoldEnd.softWrapLinesBeforeCurrentLogicalLine,
|
||||
softWrapAwareLogFoldEnd.softWrapLinesOnCurrentLogicalLine, visiblePos.column - columnToUse - softWrapAwareLogFoldEnd.foldingColumnDiff,
|
||||
softWrapAwareLogFoldEnd.foldedLines, softWrapAwareLogFoldEnd.foldingColumnDiff
|
||||
);
|
||||
LogicalPosition logFoldEnd = offsetToLogicalPosition(lastCollapsedBefore.getEndOffset(), false);
|
||||
VisualPosition visFoldEnd = logicalToVisualPosition(logFoldEnd, false);
|
||||
|
||||
line = logFoldEnd.line + (visiblePos.line - visFoldEnd.line);
|
||||
if (visFoldEnd.line == visiblePos.line) {
|
||||
if (visiblePos.column >= visFoldEnd.column) {
|
||||
column = logFoldEnd.column + (visiblePos.column - visFoldEnd.column);
|
||||
}
|
||||
else {
|
||||
return offsetToLogicalPosition(lastCollapsedBefore.getStartOffset());
|
||||
return offsetToLogicalPosition(lastCollapsedBefore.getStartOffset(), false);
|
||||
}
|
||||
}
|
||||
|
||||
LogicalPosition softWrapUnawareLogFoldEnd = offsetToLogicalPosition(lastCollapsedBefore.getEndOffset(), false);
|
||||
VisualPosition softWrapUnawareVisFoldEnd = logicalToVisualPosition(softWrapUnawareLogFoldEnd, false);
|
||||
line = softWrapUnawareLogFoldEnd.line + (visiblePos.line - softWrapUnawareVisFoldEnd.line);
|
||||
}
|
||||
|
||||
if (column < 0) column = 0;
|
||||
line = Math.min(line, myDocument.getLineCount() - 1);
|
||||
|
||||
LogicalPosition softWrapUnawareResult = new LogicalPosition(line, column);
|
||||
return mySoftWrapModel.adjustLogicalPosition(softWrapUnawareResult, visiblePos);
|
||||
return new LogicalPosition(line, column);
|
||||
}
|
||||
|
||||
private int calcLogicalLineNumber(int offset) {
|
||||
@@ -2746,7 +2759,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
int column = EditorUtil.calcColumnNumber(this, text, start, offset, EditorUtil.getTabSize(this));
|
||||
|
||||
if (softWrapAware) {
|
||||
int line = calcLogicalLineNumber(offset, false);
|
||||
int line = calcLogicalLineNumber(offset, false);
|
||||
return mySoftWrapModel.adjustLogicalPosition(new LogicalPosition(line, column), offset).column;
|
||||
}
|
||||
else {
|
||||
@@ -2886,22 +2899,22 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
int x = myGutterComponent.convertX(e.getX());
|
||||
|
||||
if (x >= myGutterComponent.getLineNumberAreaOffset() &&
|
||||
x < myGutterComponent.getLineNumberAreaOffset() + myGutterComponent.getLineNumberAreaWidth()) {
|
||||
x < myGutterComponent.getLineNumberAreaOffset() + myGutterComponent.getLineNumberAreaWidth()) {
|
||||
return EditorMouseEventArea.LINE_NUMBERS_AREA;
|
||||
}
|
||||
|
||||
if (x >= myGutterComponent.getAnnotationsAreaOffset() &&
|
||||
x <= myGutterComponent.getAnnotationsAreaOffset() + myGutterComponent.getAnnotationsAreaWidth()) {
|
||||
x <= myGutterComponent.getAnnotationsAreaOffset() + myGutterComponent.getAnnotationsAreaWidth()) {
|
||||
return EditorMouseEventArea.ANNOTATIONS_AREA;
|
||||
}
|
||||
|
||||
if (x >= myGutterComponent.getLineMarkerAreaOffset() &&
|
||||
x < myGutterComponent.getLineMarkerAreaOffset() + myGutterComponent.getLineMarkerAreaWidth()) {
|
||||
x < myGutterComponent.getLineMarkerAreaOffset() + myGutterComponent.getLineMarkerAreaWidth()) {
|
||||
return EditorMouseEventArea.LINE_MARKERS_AREA;
|
||||
}
|
||||
|
||||
if (x >= myGutterComponent.getFoldingAreaOffset() &&
|
||||
x < myGutterComponent.getFoldingAreaOffset() + myGutterComponent.getFoldingAreaWidth()) {
|
||||
x < myGutterComponent.getFoldingAreaOffset() + myGutterComponent.getFoldingAreaWidth()) {
|
||||
return EditorMouseEventArea.FOLDING_OUTLINE_AREA;
|
||||
}
|
||||
|
||||
@@ -2993,7 +3006,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
int caretShift = newCaretOffset - mySavedSelectionStart;
|
||||
|
||||
if (myMousePressedEvent != null && getMouseEventArea(myMousePressedEvent) != EditorMouseEventArea.EDITING_AREA &&
|
||||
getMouseEventArea(myMousePressedEvent) != EditorMouseEventArea.LINE_NUMBERS_AREA) {
|
||||
getMouseEventArea(myMousePressedEvent) != EditorMouseEventArea.LINE_NUMBERS_AREA) {
|
||||
selectionModel.setSelection(oldSelectionStart, newCaretOffset);
|
||||
}
|
||||
else {
|
||||
@@ -4025,8 +4038,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
runMouseReleasedCommand(e);
|
||||
if (!e.isConsumed() && myMousePressedEvent != null && !myMousePressedEvent.isConsumed() &&
|
||||
Math.abs(e.getX() - myMousePressedEvent.getX()) < EditorUtil.getSpaceWidth(Font.PLAIN, EditorImpl.this) &&
|
||||
Math.abs(e.getY() - myMousePressedEvent.getY()) < getLineHeight()) {
|
||||
Math.abs(e.getX() - myMousePressedEvent.getX()) < EditorUtil.getSpaceWidth(Font.PLAIN, EditorImpl.this) &&
|
||||
Math.abs(e.getY() - myMousePressedEvent.getY()) < getLineHeight()) {
|
||||
runMouseClickedCommand(e);
|
||||
}
|
||||
myMousePressedEvent = null;
|
||||
@@ -4182,7 +4195,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
|
||||
myMouseSelectedRegion = myFoldingModel.getFoldingPlaceholderAt(new Point(x, y));
|
||||
myMousePressedInsideSelection = mySelectionModel.hasSelection() && caretOffset >= mySelectionModel.getSelectionStart() &&
|
||||
caretOffset <= mySelectionModel.getSelectionEnd();
|
||||
caretOffset <= mySelectionModel.getSelectionEnd();
|
||||
|
||||
if (!myMousePressedInsideSelection && mySelectionModel.hasBlockSelection()) {
|
||||
int[] starts = mySelectionModel.getBlockSelectionStarts();
|
||||
@@ -4568,7 +4581,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
final Editor editor = getEditor(source);
|
||||
if (action == MOVE && !editor.isViewer()) {
|
||||
if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), editor.getProject())) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
CommandProcessor.getInstance().executeCommand(((EditorImpl)editor).myProject, new Runnable() {
|
||||
public void run() {
|
||||
@@ -4641,7 +4654,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
myMaxWidth = mySize != null ? mySize.width : -1;
|
||||
}
|
||||
|
||||
myOldEndLine = getVisualPositionLine(e.getOffset() + e.getOldLength());
|
||||
myOldEndLine = offsetToLogicalPosition(e.getOffset() + e.getOldLength()).line;
|
||||
}
|
||||
|
||||
private int getVisualPositionLine(int offset) {
|
||||
@@ -4672,15 +4685,15 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
myLineWidths.insert(oldEndLine + 1, delta);
|
||||
}
|
||||
else if (oldEndLine > newEndLine && !toAddNewLines && newEndLine + 1 < lineWidthSize) {
|
||||
myLineWidths.remove(newEndLine + 1, Math.min(oldEndLine, lineWidthSize) - newEndLine);
|
||||
myLineWidths.remove(newEndLine + 1, Math.min(oldEndLine, lineWidthSize) - newEndLine - 1);
|
||||
}
|
||||
myIsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
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 startLine = e.getOldLength() == 0 ? myOldEndLine : offsetToLogicalPosition(e.getOffset()).line;
|
||||
int newEndLine = e.getNewLength() == 0 ? startLine : offsetToLogicalPosition(e.getOffset() + e.getNewLength()).line;
|
||||
int oldEndLine = myOldEndLine;
|
||||
|
||||
update(startLine, newEndLine, oldEndLine);
|
||||
@@ -4844,7 +4857,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
TextChange softWrap = getSoftWrapModel().getSoftWrap(i);
|
||||
if (softWrap != null) {
|
||||
column++; // For 'after soft wrap' drawing.
|
||||
x = getSoftWrapModel().getMinDrawingWidth(SoftWrapDrawingType.AFTER_SOFT_WRAP);
|
||||
x = getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP);
|
||||
}
|
||||
|
||||
char c = text.charAt(i);
|
||||
@@ -4882,7 +4895,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
: e.isControlDown() && !e.isMetaDown() && !e.isAltDown() && !e.isShiftDown();
|
||||
if (changeFontSize) {
|
||||
setFontSize(myScheme.getEditorFontSize() + e.getWheelRotation());
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+22
-8
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.intellij.openapi.editor.impl;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Strategy interface for various utility methods used for representing document text at the editor.
|
||||
* <p/>
|
||||
@@ -37,16 +39,28 @@ public interface EditorTextRepresentationHelper {
|
||||
* @param x <code>'x'</code> offset from the visual line start
|
||||
* @return number of visual columns necessary for the target text sub-sequence representation
|
||||
*/
|
||||
int toVisualColumnSymbolsNumber(CharSequence text, int start, int end, int x);
|
||||
int toVisualColumnSymbolsNumber(@NotNull CharSequence text, int start, int end, int x);
|
||||
|
||||
/**
|
||||
* Allows to retrieve width (in pixels) necessary to represent given symbol at the given <code>'x'</code> offset from
|
||||
* visual line start using given font type.
|
||||
* Allows to answer how many visual columns is necessary for representing text of the given width.
|
||||
*
|
||||
* @param c target symbol which width should be calculated
|
||||
* @param x current <code>'x'</code> of the visual line start to use for the target symbol representation
|
||||
* @param fontType font type to use for representing given symbol
|
||||
* @return number of pixels necessary for the given symbol representation
|
||||
* @param width target width
|
||||
* @return number of visual columns necessary for representation of the text with the given width
|
||||
*/
|
||||
int charWidth(char c, int x, int fontType);
|
||||
int toVisualColumnSymbolsNumber(int width);
|
||||
|
||||
/**
|
||||
* Allows to retrieve width (in pixels) necessary to represent given region (<code>[start; end)</code>) starting
|
||||
* at the given <code>'x'</code> offset from visual line start using given font type.
|
||||
* <p/>
|
||||
* <b>Note:</b> target region is allows to contain line feeds, the width is calculated as a difference between <code>'x'</code>
|
||||
* coordinates of the last and first symbols.
|
||||
*
|
||||
* @param text target text holder
|
||||
* @param start start offset of the target text sub-sequence (inclusive)
|
||||
* @param end end offset of the target text sub-sequence (exclusive)
|
||||
* @param x <code>'x'</code> offset from the visual line start
|
||||
* @return width in pixels necessary for the target text sub-sequence representation
|
||||
*/
|
||||
int textWidth(@NotNull CharSequence text, int start, int end, int x);
|
||||
}
|
||||
|
||||
+31
-17
@@ -43,7 +43,7 @@ import java.util.List;
|
||||
*/
|
||||
public class SoftWrapModelImpl implements SoftWrapModelEx {
|
||||
|
||||
private final SoftWrapDataMapper myDataAdjuster;
|
||||
private final SoftWrapDataMapper myDataMapper;
|
||||
private final SoftWrapsStorage myStorage;
|
||||
private final SoftWrapPainter myPainter;
|
||||
private final SoftWrapApplianceManager myApplianceManager;
|
||||
@@ -60,20 +60,20 @@ public class SoftWrapModelImpl implements SoftWrapModelEx {
|
||||
public SoftWrapModelImpl(@NotNull final EditorEx editor, @NotNull SoftWrapsStorage storage, @NotNull SoftWrapPainter painter) {
|
||||
this(
|
||||
editor, storage, painter, new DefaultSoftWrapApplianceManager(storage, editor, painter),
|
||||
new SoftWrapDataMapper(editor, storage, painter, new DefaultEditorTextRepresentationHelper(editor)),
|
||||
new SoftWrapDataMapper(editor, storage, new DefaultEditorTextRepresentationHelper(editor)),
|
||||
new SoftWrapDocumentChangeManager(editor, storage)
|
||||
);
|
||||
}
|
||||
|
||||
public SoftWrapModelImpl(@NotNull EditorEx editor, @NotNull SoftWrapsStorage storage, @NotNull SoftWrapPainter painter,
|
||||
@NotNull SoftWrapApplianceManager applianceManager, @NotNull SoftWrapDataMapper dataAdjuster,
|
||||
@NotNull SoftWrapApplianceManager applianceManager, @NotNull SoftWrapDataMapper dataMapper,
|
||||
@NotNull SoftWrapDocumentChangeManager documentChangeManager)
|
||||
{
|
||||
myEditor = editor;
|
||||
myStorage = storage;
|
||||
myPainter = painter;
|
||||
myApplianceManager = applianceManager;
|
||||
myDataAdjuster = dataAdjuster;
|
||||
myDataMapper = dataMapper;
|
||||
myDocumentChangeManager = documentChangeManager;
|
||||
}
|
||||
|
||||
@@ -184,25 +184,39 @@ public class SoftWrapModelImpl implements SoftWrapModelEx {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinDrawingWidth(@NotNull SoftWrapDrawingType drawingType) {
|
||||
public int getMinDrawingWidthInPixels(@NotNull SoftWrapDrawingType drawingType) {
|
||||
return myPainter.getMinDrawingWidth(drawingType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinDrawingWidthInColumns(@NotNull SoftWrapDrawingType drawingType) {
|
||||
return myPainter.getMinDrawingWidth(drawingType) > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public LogicalPosition adjustLogicalPosition(@NotNull LogicalPosition defaultLogical, @NotNull VisualPosition visual) {
|
||||
@Override
|
||||
public LogicalPosition visualToLogicalPosition(@NotNull VisualPosition visual) {
|
||||
if (myActive > 0 || !isSoftWrappingEnabled() || myStorage.isEmpty() || myEditor.getDocument().getTextLength() <= 0) {
|
||||
return defaultLogical;
|
||||
return myEditor.visualToLogicalPosition(visual, false);
|
||||
}
|
||||
|
||||
if (defaultLogical.visualPositionAware) {
|
||||
return defaultLogical;
|
||||
}
|
||||
|
||||
myActive++;
|
||||
try {
|
||||
return myDataAdjuster.adjustLogicalPosition(defaultLogical, visual);
|
||||
return myDataMapper.visualToLogical(visual);
|
||||
} finally {
|
||||
myActive--;
|
||||
}
|
||||
finally {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public LogicalPosition offsetToLogicalPosition(int offset) {
|
||||
if (myActive > 0 || !isSoftWrappingEnabled() || myStorage.isEmpty() || myEditor.getDocument().getTextLength() <= 0) {
|
||||
return myEditor.offsetToLogicalPosition(offset, false);
|
||||
}
|
||||
myActive++;
|
||||
try {
|
||||
return myDataMapper.offsetToLogicalPosition(offset);
|
||||
} finally {
|
||||
myActive--;
|
||||
}
|
||||
}
|
||||
@@ -215,7 +229,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx {
|
||||
|
||||
myActive++;
|
||||
try {
|
||||
return myDataAdjuster.offsetToLogicalPosition(offset);
|
||||
return myDataMapper.offsetToLogicalPosition(offset);
|
||||
} finally {
|
||||
myActive--;
|
||||
}
|
||||
@@ -229,7 +243,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx {
|
||||
|
||||
myActive++;
|
||||
try {
|
||||
return myDataAdjuster.adjustVisualPosition(logical, defaultVisual);
|
||||
return myDataMapper.adjustVisualPosition(logical, defaultVisual);
|
||||
}
|
||||
finally {
|
||||
myActive--;
|
||||
@@ -292,7 +306,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx {
|
||||
}
|
||||
|
||||
if (start < end) {
|
||||
result += EditorUtil.textWidth(myEditor, chars, start, end, Font.PLAIN, 0);
|
||||
result += EditorUtil.textWidth(myEditor, softWrap.getText(), start, end, Font.PLAIN, 0);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
+3
-1
@@ -29,6 +29,8 @@ import gnu.trove.TIntArrayList;
|
||||
import gnu.trove.TIntHashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.nio.CharBuffer;
|
||||
|
||||
/**
|
||||
* Default {@link SoftWrapApplianceManager} implementation that is built with the following design guide lines:
|
||||
* <pre>
|
||||
@@ -214,7 +216,7 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager
|
||||
int x = myPainter.getMinDrawingWidth(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED);
|
||||
int prevSoftWrapOffset = start;
|
||||
for (int i = start; i < end; i++) {
|
||||
int symbolWidth = EditorUtil.textWidth(myEditor, text, i, i + 1, fontType, x);
|
||||
int symbolWidth = EditorUtil.textWidth(myEditor, CharBuffer.wrap(text), i, i + 1, fontType, x);
|
||||
if (x + symbolWidth >= myVisibleAreaWidth) {
|
||||
int offset = calculateSoftWrapOffset(text, i - 1, prevSoftWrapOffset, end);
|
||||
if (offset >= end || offset <= prevSoftWrapOffset) {
|
||||
|
||||
+407
-524
File diff suppressed because it is too large
Load Diff
@@ -239,7 +239,7 @@ public class IdeRootPane extends JRootPane implements UISettingsListener {
|
||||
return c.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
public WidgetPresentation getPresentation(@NotNull Type type) {
|
||||
public WidgetPresentation getPresentation(@NotNull PlatformType type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ public class EncodingPanel implements StatusBarWidget, StatusBarWidget.MultipleT
|
||||
return "Encoding";
|
||||
}
|
||||
|
||||
public WidgetPresentation getPresentation(@NotNull Type type) {
|
||||
public WidgetPresentation getPresentation(@NotNull PlatformType type) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
+32
-20
@@ -16,6 +16,7 @@
|
||||
package com.intellij.openapi.wm.impl.status;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.TaskInfo;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.ui.popup.BalloonHandler;
|
||||
@@ -42,15 +43,15 @@ import javax.swing.event.HyperlinkListener;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* User: spLeaner
|
||||
*/
|
||||
public class IdeStatusBarImpl extends JComponent implements StatusBarEx {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.status.IdeStatusBarImpl");
|
||||
|
||||
private InfoAndProgressPanel myInfoAndProgressPanel;
|
||||
|
||||
private enum Position {LEFT, RIGHT, CENTER}
|
||||
@@ -93,7 +94,7 @@ public class IdeStatusBarImpl extends JComponent implements StatusBarEx {
|
||||
}
|
||||
|
||||
public void addWidget(@NotNull final StatusBarWidget widget) {
|
||||
addWidget(widget, Position.RIGHT, "before Notifications");
|
||||
addWidget(widget, Position.RIGHT, "__AUTODETECT__");
|
||||
}
|
||||
|
||||
public void addWidget(@NotNull final StatusBarWidget widget, @NotNull String anchor) {
|
||||
@@ -139,7 +140,7 @@ public class IdeStatusBarImpl extends JComponent implements StatusBarEx {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public WidgetPresentation getPresentation(@NotNull Type type) {
|
||||
public WidgetPresentation getPresentation(@NotNull PlatformType type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -158,19 +159,23 @@ public class IdeStatusBarImpl extends JComponent implements StatusBarEx {
|
||||
}
|
||||
|
||||
public void removeCustomIndicationComponent(@NotNull final JComponent c) {
|
||||
for (final String key : myWidgetMap.keySet()) {
|
||||
final WidgetBean bean = myWidgetMap.get(key);
|
||||
if (bean.component instanceof CustomStatusBarWidget && ((CustomStatusBarWidget)bean.component).getComponent() == c) {
|
||||
final Set<String> keySet = myWidgetMap.keySet();
|
||||
final String[] keys = keySet.toArray(new String[keySet.size()]);
|
||||
for (final String key : keys) {
|
||||
final WidgetBean value = myWidgetMap.get(key);
|
||||
if (value.widget instanceof CustomStatusBarWidget && value.component == c) {
|
||||
removeWidget(key);
|
||||
myCustomComponentIds.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
for (final String key : myWidgetMap.keySet()) {
|
||||
final WidgetBean bean = myWidgetMap.get(key);
|
||||
for (final WidgetBean bean : myWidgetMap.values()) {
|
||||
Disposer.dispose(bean.widget);
|
||||
}
|
||||
|
||||
myWidgetMap.clear();
|
||||
}
|
||||
|
||||
private void addWidget(@NotNull final StatusBarWidget widget, @NotNull final Position pos, @NotNull String anchor) {
|
||||
@@ -207,20 +212,29 @@ public class IdeStatusBarImpl extends JComponent implements StatusBarEx {
|
||||
|
||||
final JComponent c = widget instanceof CustomStatusBarWidget ? ((CustomStatusBarWidget)widget).getComponent() : wrap(widget);
|
||||
if (Position.RIGHT == pos && panel.getComponentCount() > 0) {
|
||||
final List<String> parts = StringUtil.split(anchor, " ");
|
||||
if (parts.size() < 2) {
|
||||
throw new IllegalArgumentException(
|
||||
"anchor should be a relative position ('before' or 'after') and widget ID, like 'after Encoding'");
|
||||
String wid;
|
||||
boolean before;
|
||||
if (!anchor.equals("__AUTODETECT__")) {
|
||||
final List<String> parts = StringUtil.split(anchor, " ");
|
||||
if (parts.size() < 2 || !myWidgetMap.keySet().contains(parts.get(1))) {
|
||||
wid = "Notifications";
|
||||
before = true;
|
||||
} else {
|
||||
wid = parts.get(1);
|
||||
before = "before".equalsIgnoreCase(parts.get(0));
|
||||
}
|
||||
} else {
|
||||
wid = "Notifications";
|
||||
before = true;
|
||||
}
|
||||
|
||||
for (final String id : myWidgetMap.keySet()) {
|
||||
if (id.equalsIgnoreCase(parts.get(1))) {
|
||||
if (id.equalsIgnoreCase(wid)) {
|
||||
final WidgetBean bean = myWidgetMap.get(id);
|
||||
int i = 0;
|
||||
for (final Component component : myRightPanel.getComponents()) {
|
||||
if (component == bean.component) {
|
||||
final String _relative = parts.get(0);
|
||||
if ("before".equalsIgnoreCase(_relative)) {
|
||||
if (before) {
|
||||
panel.add(c, i);
|
||||
updateBorder(i);
|
||||
}
|
||||
@@ -238,8 +252,6 @@ public class IdeStatusBarImpl extends JComponent implements StatusBarEx {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("unable to find widget with id: " + parts.get(1));
|
||||
}
|
||||
|
||||
if (Position.LEFT == pos && panel.getComponentCount() == 0) {
|
||||
@@ -323,7 +335,7 @@ public class IdeStatusBarImpl extends JComponent implements StatusBarEx {
|
||||
|
||||
private static JComponent wrap(@NotNull final StatusBarWidget widget) {
|
||||
final StatusBarWidget.WidgetPresentation presentation =
|
||||
widget.getPresentation(SystemInfo.isMac ? StatusBarWidget.Type.MAC : StatusBarWidget.Type.DEFAULT);
|
||||
widget.getPresentation(SystemInfo.isMac ? StatusBarWidget.PlatformType.MAC : StatusBarWidget.PlatformType.DEFAULT);
|
||||
assert presentation != null : "Presentation should not be null!";
|
||||
|
||||
JComponent wrapper;
|
||||
|
||||
+1
-6
@@ -18,15 +18,12 @@ package com.intellij.openapi.wm.impl.status;
|
||||
import com.intellij.idea.ActionsBundle;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx;
|
||||
import com.intellij.openapi.progress.TaskInfo;
|
||||
import com.intellij.openapi.progress.impl.ProgressManagerImpl;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.ui.popup.Balloon;
|
||||
import com.intellij.openapi.ui.popup.BalloonHandler;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.util.MultiValuesMap;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.wm.CustomStatusBarWidget;
|
||||
@@ -52,9 +49,7 @@ import javax.swing.event.HyperlinkListener;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
public class InfoAndProgressPanel extends JPanel implements CustomStatusBarWidget {
|
||||
private final ProcessPopup myPopup;
|
||||
@@ -142,7 +137,7 @@ public class InfoAndProgressPanel extends JPanel implements CustomStatusBarWidge
|
||||
return "InfoAndProgress";
|
||||
}
|
||||
|
||||
public WidgetPresentation getPresentation(@NotNull Type type) {
|
||||
public WidgetPresentation getPresentation(@NotNull PlatformType type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ public class InsertOverwritePanel implements StatusBarWidget, StatusBarWidget.Te
|
||||
return "InsertOverwrite";
|
||||
}
|
||||
|
||||
public WidgetPresentation getPresentation(@NotNull Type type) {
|
||||
public WidgetPresentation getPresentation(@NotNull PlatformType type) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -70,7 +70,7 @@ public class MemoryUsagePanel extends JButton implements CustomStatusBarWidget {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public WidgetPresentation getPresentation(@NotNull Type type) {
|
||||
public WidgetPresentation getPresentation(@NotNull PlatformType type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ public class PositionPanel implements StatusBarWidget, StatusBarWidget.TextPrese
|
||||
return "Position";
|
||||
}
|
||||
|
||||
public WidgetPresentation getPresentation(@NotNull final Type type) {
|
||||
public WidgetPresentation getPresentation(@NotNull final PlatformType type) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,16 +30,16 @@ public class TextPanel extends JComponent {
|
||||
private boolean myDecorate = true;
|
||||
private float myAlignment;
|
||||
|
||||
TextPanel() {
|
||||
protected TextPanel() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
TextPanel(final boolean decorate) {
|
||||
protected TextPanel(final boolean decorate) {
|
||||
this(null);
|
||||
myDecorate = decorate;
|
||||
}
|
||||
|
||||
TextPanel(@Nullable final String maxPossibleString) {
|
||||
protected TextPanel(@Nullable final String maxPossibleString) {
|
||||
myMaxPossibleString = maxPossibleString;
|
||||
|
||||
setFont(SystemInfo.isMac ? UIUtil.getLabelFont().deriveFont(11.0f) : UIUtil.getLabelFont());
|
||||
@@ -93,7 +93,7 @@ public class TextPanel extends JComponent {
|
||||
final int y = UIUtil.getStringY(s, bounds, g2);
|
||||
if (SystemInfo.isMac && myDecorate) {
|
||||
g2.setColor(new Color(215, 215, 215));
|
||||
g2.drawString(s, x, y+1);
|
||||
g2.drawString(s, x, y + 1);
|
||||
}
|
||||
|
||||
g2.setColor(getForeground());
|
||||
@@ -105,7 +105,7 @@ public class TextPanel extends JComponent {
|
||||
myAlignment = alignment;
|
||||
}
|
||||
|
||||
private static String splitText(final JLabel label, final String text, final int widthLimit){
|
||||
private static String splitText(final JLabel label, final String text, final int widthLimit) {
|
||||
final FontMetrics fontMetrics = label.getFontMetrics(label.getFont());
|
||||
|
||||
final String[] lines = UIUtil.splitText(text, fontMetrics, widthLimit, ' ');
|
||||
@@ -130,9 +130,10 @@ public class TextPanel extends JComponent {
|
||||
return myText;
|
||||
}
|
||||
|
||||
public Dimension getPreferredSize(){
|
||||
public Dimension getPreferredSize() {
|
||||
int max = 0;
|
||||
if (myMaxPossibleString != null) max = getFontMetrics(getFont()).stringWidth(myMaxPossibleString);
|
||||
String text = getTextForPreferredSize();
|
||||
if (text != null) max = getFontMetrics(getFont()).stringWidth(text);
|
||||
|
||||
if (myPrefSize != null) {
|
||||
return new Dimension(20 + max, myPrefSize.height);
|
||||
@@ -140,4 +141,11 @@ public class TextPanel extends JComponent {
|
||||
|
||||
return new Dimension(20 + max, getMinimumSize().height);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the text that is used to calculate the preferred size
|
||||
*/
|
||||
protected String getTextForPreferredSize() {
|
||||
return myMaxPossibleString;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ public class ToggleReadOnlyAttributePanel implements StatusBarWidget, StatusBarW
|
||||
return "ReadOnlyAttribute";
|
||||
}
|
||||
|
||||
public WidgetPresentation getPresentation(@NotNull Type type) {
|
||||
public WidgetPresentation getPresentation(@NotNull PlatformType type) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
+119
-35
@@ -3,10 +3,13 @@ package com.intellij.openapi.editor.impl.softwrap;
|
||||
import com.intellij.mock.MockFoldRegion;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.ex.FoldingModelEx;
|
||||
import com.intellij.openapi.editor.ex.SoftWrapModelEx;
|
||||
import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import gnu.trove.TIntHashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
@@ -18,7 +21,6 @@ import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
@@ -88,7 +90,8 @@ public class SoftWrapDataMapperTest {
|
||||
private EditorEx myEditor;
|
||||
private Document myDocument;
|
||||
private SoftWrapsStorage myStorage;
|
||||
private FoldingModel myFoldingModel;
|
||||
private SoftWrapModelEx mySoftWrapModel;
|
||||
private FoldingModelEx myFoldingModel;
|
||||
private MockEditorTextRepresentationHelper myRepresentationHelper;
|
||||
|
||||
@Before
|
||||
@@ -100,7 +103,8 @@ public class SoftWrapDataMapperTest {
|
||||
myEditor = myMockery.mock(EditorEx.class);
|
||||
myDocument = myMockery.mock(Document.class);
|
||||
myStorage = new SoftWrapsStorage();
|
||||
myFoldingModel = myMockery.mock(FoldingModel.class);
|
||||
mySoftWrapModel = myMockery.mock(SoftWrapModelEx.class);
|
||||
myFoldingModel = myMockery.mock(FoldingModelEx.class);
|
||||
final EditorSettings settings = myMockery.mock(EditorSettings.class);
|
||||
final Project project = myMockery.mock(Project.class);
|
||||
final SoftWrapPainter painter = myMockery.mock(SoftWrapPainter.class);
|
||||
@@ -140,6 +144,23 @@ public class SoftWrapDataMapperTest {
|
||||
allowing(settings).isWhitespacesShown();will(returnValue(true));
|
||||
allowing(myEditor).getProject();will(returnValue(project));
|
||||
|
||||
// Soft wraps.
|
||||
allowing(myEditor).getSoftWrapModel(); will(returnValue(mySoftWrapModel));
|
||||
allowing(mySoftWrapModel).getSoftWrapIndentWidthInColumns(with(any(TextChange.class)));
|
||||
will(new CustomAction("getSoftWrapIndentWidthInColumns") {
|
||||
@Override
|
||||
public Object invoke(Invocation invocation) throws Throwable {
|
||||
return getSoftWrapIndentWidthInColumns((TextChange)invocation.getParameter(0));
|
||||
}
|
||||
});
|
||||
allowing(mySoftWrapModel).getSoftWrapIndentWidthInPixels(with(any(TextChange.class)));
|
||||
will(new CustomAction("getSoftWrapIndentWidthInPixels") {
|
||||
@Override
|
||||
public Object invoke(Invocation invocation) throws Throwable {
|
||||
return getSoftWrapIndentWidthInPixels((TextChange)invocation.getParameter(0));
|
||||
}
|
||||
});
|
||||
|
||||
// Folding.
|
||||
allowing(myEditor).getFoldingModel();will(returnValue(myFoldingModel));
|
||||
allowing(myFoldingModel).isOffsetCollapsed(with(any(int.class))); will(new CustomAction("isOffsetCollapsed()") {
|
||||
@@ -155,7 +176,7 @@ public class SoftWrapDataMapperTest {
|
||||
return getCollapsedFoldRegion((Integer)invocation.getParameter(0));
|
||||
}
|
||||
});
|
||||
allowing(myFoldingModel).getAllFoldRegions(); will(new CustomAction("getAllFoldRegions()") {
|
||||
allowing(myFoldingModel).fetchTopLevel(); will(new CustomAction("fetchTopLevel()") {
|
||||
@Override
|
||||
public Object invoke(Invocation invocation) throws Throwable {
|
||||
return myFoldRegions.toArray(new FoldRegion[myFoldRegions.size()]);
|
||||
@@ -188,7 +209,7 @@ public class SoftWrapDataMapperTest {
|
||||
|
||||
myRepresentationHelper = new MockEditorTextRepresentationHelper();
|
||||
|
||||
myAdjuster = new SoftWrapDataMapper(myEditor, myStorage, painter, myRepresentationHelper, new MockFontTypeProvider());
|
||||
myAdjuster = new SoftWrapDataMapper(myEditor, myStorage, myRepresentationHelper/*, new MockFontTypeProvider()*/);
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -196,6 +217,16 @@ public class SoftWrapDataMapperTest {
|
||||
myMockery.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noSoftWrapsAndFolding() {
|
||||
String document =
|
||||
"class Test { \n" +
|
||||
" public void foo() {} \n" +
|
||||
" \n" +
|
||||
"}";
|
||||
test(document);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void softWrapHasSymbolBeforeFirstLineFeed() {
|
||||
String document =
|
||||
@@ -216,13 +247,13 @@ public class SoftWrapDataMapperTest {
|
||||
String document =
|
||||
"public class Test {\n" +
|
||||
" public void foo(int[] data) {\n" +
|
||||
" bar(data[0], data[1], <WRAP>\n" +
|
||||
" </WRAP>data[2], data[3], <WRAP> \n" +
|
||||
" </WRAP>data[4], data[5], \n" +
|
||||
" data[6], data[7], \n" +
|
||||
" data[8], data[9], <WRAP>\n" +
|
||||
" </WRAP>data[10], data[11], <WRAP> \n" +
|
||||
" </WRAP>data[12], data[13]); \n" +
|
||||
" bar(data[0], <WRAP>\n" +
|
||||
" </WRAP>data[1] <WRAP> \n" +
|
||||
" </WRAP>data[2] \n" +
|
||||
" data[3], \n" +
|
||||
" data[4], <WRAP>\n" +
|
||||
" </WRAP>data[5] <WRAP> \n" +
|
||||
" </WRAP>data[6]); \n" +
|
||||
" }\n" +
|
||||
" public void bar(int ... i) {\n" +
|
||||
" }\n" +
|
||||
@@ -345,6 +376,34 @@ public class SoftWrapDataMapperTest {
|
||||
test(document);
|
||||
}
|
||||
|
||||
private static int getSoftWrapIndentWidthInColumns(TextChange softWrap) {
|
||||
int result = 0;
|
||||
CharSequence text = softWrap.getText();
|
||||
for (int i = text.length() - 1; i >= 0; i--) {
|
||||
if (text.charAt(i) == '\n') {
|
||||
break;
|
||||
}
|
||||
result++;
|
||||
}
|
||||
if (SOFT_WRAP_DRAWING_WIDTH > 0) {
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private int getSoftWrapIndentWidthInPixels(TextChange softWrap) {
|
||||
int result = 0;
|
||||
CharSequence text = softWrap.getText();
|
||||
for (int i = text.length() - 1; i >= 0; i--) {
|
||||
if (text.charAt(i) == '\n') {
|
||||
break;
|
||||
}
|
||||
result += myRepresentationHelper.textWidth(text, i, i + 1, 0);
|
||||
}
|
||||
result += SOFT_WRAP_DRAWING_WIDTH;
|
||||
return result;
|
||||
}
|
||||
|
||||
private int getLineNumber(int offset) {
|
||||
int line = 0;
|
||||
for (TextRange range : myLineRanges) {
|
||||
@@ -430,10 +489,12 @@ public class SoftWrapDataMapperTest {
|
||||
for (DataEntry data : myExpectedData) {
|
||||
|
||||
// Check logical by visual.
|
||||
LogicalPosition actualLogicalByVisual = myAdjuster.adjustLogicalPosition(toSoftWrapUnawareLogicalByVisual(data), data.visual);
|
||||
LogicalPosition actualLogicalByVisual = myAdjuster.visualToLogical(data.visual);
|
||||
// We don't want to perform the check for logical positions that correspond to the folded space because all of them relate to
|
||||
// the same logical position of the folding start.
|
||||
if (!data.foldedSpace && !data.insideTab && !equals(data.logical, actualLogicalByVisual)) {
|
||||
//TODO den remove
|
||||
myAdjuster.visualToLogical(data.visual);
|
||||
throw new AssertionError(
|
||||
String.format("Detected unmatched logical position by visual (%s). Expected: '%s', actual: '%s'. Calculation was performed "
|
||||
+ "against soft wrap-unaware logical: '%s'",
|
||||
@@ -446,6 +507,8 @@ public class SoftWrapDataMapperTest {
|
||||
// We don't to perform the check for the data that points to soft wrap location here. The reason is that it shares offset
|
||||
// with the first document symbol after soft wrap, hence, examination always fails.
|
||||
if (!data.virtualSpace && !data.insideTab && !equals(data.logical, actualLogicalByOffset)) {
|
||||
//TODO den remove
|
||||
myAdjuster.offsetToLogicalPosition(data.offset);
|
||||
throw new AssertionError(
|
||||
String.format("Detected unmatched logical position by offset. Expected: '%s', actual: '%s'. Calculation was performed "
|
||||
+ "against offset: '%d' and soft wrap-unaware logical: '%s'",
|
||||
@@ -635,7 +698,7 @@ public class SoftWrapDataMapperTest {
|
||||
}
|
||||
else if (c == '\t') {
|
||||
int tabWidthInColumns = myRepresentationHelper.toVisualColumnSymbolsNumber(c, x);
|
||||
x += myRepresentationHelper.charWidth(c, x, Font.PLAIN);
|
||||
x += MockEditorTextRepresentationHelper.charWidth(c, x);
|
||||
|
||||
// There is a possible case that single tabulation symbols is shown in more than one visual column at IntelliJ editor.
|
||||
// We store data entry only for the first tab column without 'inside tab' flag then.
|
||||
@@ -652,7 +715,7 @@ public class SoftWrapDataMapperTest {
|
||||
} else {
|
||||
logicalColumn++;
|
||||
offset++;
|
||||
x += myRepresentationHelper.charWidth(c, x, Font.PLAIN);
|
||||
x += MockEditorTextRepresentationHelper.charWidth(c, x);
|
||||
foldingColumnDiff--;
|
||||
}
|
||||
return;
|
||||
@@ -685,7 +748,7 @@ public class SoftWrapDataMapperTest {
|
||||
visualColumn++;
|
||||
softWrapColumnDiff++;
|
||||
softWrapSymbolsOnCurrentVisualLine++;
|
||||
x += myRepresentationHelper.charWidth(c, x, Font.PLAIN);
|
||||
x += MockEditorTextRepresentationHelper.charWidth(c, x);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -706,7 +769,7 @@ public class SoftWrapDataMapperTest {
|
||||
}
|
||||
else if (c == '\t') {
|
||||
int tabWidthInColumns = myRepresentationHelper.toVisualColumnSymbolsNumber(c, x);
|
||||
x += myRepresentationHelper.charWidth(c, x, Font.PLAIN);
|
||||
x += MockEditorTextRepresentationHelper.charWidth(c, x);
|
||||
|
||||
// There is a possible case that single tabulation symbols is shown in more than one visual column at IntelliJ editor.
|
||||
// We store data entry only for the first tab column without 'inside tab' flag then.
|
||||
@@ -726,7 +789,7 @@ public class SoftWrapDataMapperTest {
|
||||
visualColumn++;
|
||||
logicalColumn++;
|
||||
offset++;
|
||||
x += myRepresentationHelper.charWidth(c, x, Font.PLAIN);
|
||||
x += MockEditorTextRepresentationHelper.charWidth(c, x);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -782,10 +845,10 @@ public class SoftWrapDataMapperTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int toVisualColumnSymbolsNumber(CharSequence text, int start, int end, int x) {
|
||||
public int toVisualColumnSymbolsNumber(@NotNull CharSequence text, int start, int end, int x) {
|
||||
int result = 0;
|
||||
for (int i = start; i < end; i++) {
|
||||
int width = charWidth(text.charAt(i), x, Font.PLAIN);
|
||||
int width = charWidth(text.charAt(i), x);
|
||||
result += width / SPACE_SIZE;
|
||||
if (width % SPACE_SIZE > 0) {
|
||||
result++;
|
||||
@@ -796,7 +859,28 @@ public class SoftWrapDataMapperTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int charWidth(char c, int x, int fontType) {
|
||||
public int toVisualColumnSymbolsNumber(int width) {
|
||||
int result = width / SPACE_SIZE;
|
||||
if (width % SPACE_SIZE > 0) {
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int textWidth(@NotNull CharSequence text, int start, int end, int x) {
|
||||
int result = 0;
|
||||
for (int i = start; i < end; i++) {
|
||||
char c = text.charAt(i);
|
||||
switch (c) {
|
||||
case '\n': result = 0; break;
|
||||
default: result += charWidth(c, result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int charWidth(char c, int x) {
|
||||
if (c == '\t') {
|
||||
int tabWidth = SPACE_SIZE * TAB_SIZE;
|
||||
int tabsNumber = x / tabWidth;
|
||||
@@ -808,18 +892,18 @@ public class SoftWrapDataMapperTest {
|
||||
}
|
||||
}
|
||||
|
||||
private static class MockFontTypeProvider implements SoftWrapDataMapper.FontTypeProvider {
|
||||
@Override
|
||||
public void init(int start) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFontType(int offset) {
|
||||
return Font.PLAIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
}
|
||||
}
|
||||
//private static class MockFontTypeProvider implements SoftWrapDataMapper.FontTypeProvider {
|
||||
// @Override
|
||||
// public void init(int start) {
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public int getFontType(int offset) {
|
||||
// return Font.PLAIN;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void cleanup() {
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
@@ -224,11 +224,11 @@ javadoc.external.fetch.error.message=Cannot fetch remote documentation: {0}
|
||||
searching.for.implementations=Searching For Implementations...
|
||||
|
||||
goto.implementation.chooserTitle=<html><body>Choose Implementation of <b>{0}</b> ({1} found)</body></html>
|
||||
goto.implementation.notFound=Not implementations found
|
||||
goto.implementation.notFound=No implementations found
|
||||
|
||||
goto.test.chooserTitle.test=<html><body>Choose Test for <b>{0}</b> ({1} found)</body></html>
|
||||
goto.test.chooserTitle.subject=<html><body>Choose Test Subject for <b>{0}</b> ({1} found)</body></html>
|
||||
goto.test.notFound=Not test subjects found
|
||||
goto.test.notFound=No test subjects found
|
||||
|
||||
incremental.search.tooltip.prefix=Search for:
|
||||
goto.super.method.chooser.title=Choose super method
|
||||
|
||||
@@ -32,14 +32,14 @@ el.lparen.expected=( expected
|
||||
el.rparen.expected=) expected
|
||||
el.colon.expected=: expected
|
||||
el.value.expected=Value expected
|
||||
el.cannot.resolve.function=Cannot resolve function {0} #loc
|
||||
el.cannot.resolve.namespace=Cannot resolve namespace {0} #loc
|
||||
el.cannot.resolve.property=Cannot resolve property or method {0} (dynamic property?) #loc
|
||||
el.cannot.resolve.function=Cannot resolve function ''{0}'' #loc
|
||||
el.cannot.resolve.namespace=Cannot resolve namespace ''{0}'' #loc
|
||||
el.cannot.resolve.property=Cannot resolve property or method ''{0}'' (dynamic property?) #loc
|
||||
el.mismatched.parameters.count=Different number of formal and actual parameters
|
||||
el.declare.variable.intention.family=Declare Variable As External Data
|
||||
el.declare.variable.via.usebean.intention.name=Declare external variable as <jsp:useBean />
|
||||
el.declare.variable.via.comment.annotation.intention.name=Declare external variable in comment annotation
|
||||
el.cannot.resolve.variable=Cannot resolve variable {0} #loc
|
||||
el.cannot.resolve.variable=Cannot resolve variable ''{0}'' #loc
|
||||
jsf.el.out.of.attribute=JSF EL out of attribute #loc
|
||||
jsf.method.call.is.nonstd.extension=Method call is nonstandard extension #loc
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ status.bar.insert.status.text=Insert
|
||||
status.bar.overwrite.status.text=Overwrite
|
||||
popup.hints.panel.click.to.configure.highlighting.tooltip.text=Click to configure highlighting for this file
|
||||
popup.hints.panel.click.to.configure.profile.text=Click to configure inspection profiles
|
||||
read.only.attr.panel.double.click.to.toggle.attr.tooltip.text=Double-click to toggle the read-only attribute
|
||||
read.only.attr.panel.double.click.to.toggle.attr.tooltip.text=Click to toggle the read-only attribute
|
||||
welcome.screen.get.from.vcs.action.no.vcs.plugins.with.check.out.action.installed.action.name=No VCS plugins with Check-out action installed.
|
||||
welcome.screen.get.from.vcs.action.checkout.from.list.popup.title=Checkout from
|
||||
welcome.screen.recent.projects.action.no.recent.projects.to.display.action.name=No recent projects to display.
|
||||
|
||||
+1
-2
@@ -45,7 +45,6 @@ import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.util.io.URLUtil;
|
||||
import org.apache.tools.ant.taskdefs.optional.junit.XMLConstants;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.xml.sax.SAXException;
|
||||
@@ -258,7 +257,7 @@ public class ExportTestResultsAction extends DumbAwareAction {
|
||||
else {
|
||||
Source xslSource;
|
||||
if (config.getExportFormat() == ExportTestResultsConfiguration.ExportFormat.BundledTemplate) {
|
||||
URL bundledXsltUrl = XMLConstants.class.getResource("/org/apache/tools/ant/taskdefs/optional/junit/xsl/junit-noframes.xsl");
|
||||
URL bundledXsltUrl = getClass().getResource("junit-noframes.xsl");
|
||||
xslSource = new StreamSource(URLUtil.openStream(bundledXsltUrl));
|
||||
}
|
||||
else {
|
||||
|
||||
+12
-2
@@ -24,7 +24,6 @@ import com.intellij.execution.ui.ConsoleViewContentType;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.util.PairProcessor;
|
||||
import org.apache.tools.ant.taskdefs.optional.junit.XMLConstants;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.AttributesImpl;
|
||||
@@ -34,7 +33,18 @@ import java.util.Map;
|
||||
|
||||
// this class generates resulting XML compatible to that of XMLJUnitResultFormatter
|
||||
|
||||
public class TestResultsXmlFormatter implements XMLConstants {
|
||||
public class TestResultsXmlFormatter {
|
||||
|
||||
// see org.apache.tools.ant.taskdefs.optional.junit.XmlConstants
|
||||
private static final String TESTSUITES = "testsuites";
|
||||
private static final String TESTSUITE = "testsuite";
|
||||
private static final String TESTCASE = "testcase";
|
||||
private static final String FAILURE = "failure";
|
||||
private static final String ATTR_NAME = "name";
|
||||
private static final String ATTR_FAILURES = "failures";
|
||||
private static final String ATTR_TESTS = "tests";
|
||||
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(TestResultsXmlFormatter.class.getName());
|
||||
|
||||
private final RuntimeConfiguration myRuntimeConfiguration;
|
||||
|
||||
+467
@@ -0,0 +1,467 @@
|
||||
<?xml version="1.0"?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
|
||||
xmlns:lxslt="http://xml.apache.org/xslt"
|
||||
xmlns:stringutils="xalan://org.apache.tools.ant.util.StringUtils">
|
||||
<xsl:output method="html" indent="yes" encoding="US-ASCII"
|
||||
doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN" />
|
||||
<xsl:decimal-format decimal-separator="." grouping-separator="," />
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You 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.
|
||||
-->
|
||||
|
||||
<xsl:param name="TITLE">Unit Test Results.</xsl:param>
|
||||
|
||||
<!--
|
||||
|
||||
Sample stylesheet to be used with Ant JUnitReport output.
|
||||
|
||||
It creates a non-framed report that can be useful to send via
|
||||
e-mail or such.
|
||||
|
||||
-->
|
||||
<xsl:template match="testsuites">
|
||||
<html>
|
||||
<head>
|
||||
<title><xsl:value-of select="$TITLE"/></title>
|
||||
<style type="text/css">
|
||||
body {
|
||||
font:normal 68% verdana,arial,helvetica;
|
||||
color:#000000;
|
||||
}
|
||||
table tr td, table tr th {
|
||||
font-size: 68%;
|
||||
}
|
||||
table.details tr th{
|
||||
font-weight: bold;
|
||||
text-align:left;
|
||||
background:#a6caf0;
|
||||
}
|
||||
table.details tr td{
|
||||
background:#eeeee0;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height:1.5em;
|
||||
margin-top:0.5em; margin-bottom:1.0em;
|
||||
}
|
||||
h1 {
|
||||
margin: 0px 0px 5px; font: 165% verdana,arial,helvetica
|
||||
}
|
||||
h2 {
|
||||
margin-top: 1em; margin-bottom: 0.5em; font: bold 125% verdana,arial,helvetica
|
||||
}
|
||||
h3 {
|
||||
margin-bottom: 0.5em; font: bold 115% verdana,arial,helvetica
|
||||
}
|
||||
h4 {
|
||||
margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
|
||||
}
|
||||
h5 {
|
||||
margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
|
||||
}
|
||||
h6 {
|
||||
margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
|
||||
}
|
||||
.Error {
|
||||
font-weight:bold; color:red;
|
||||
}
|
||||
.Failure {
|
||||
font-weight:bold; color:purple;
|
||||
}
|
||||
.Properties {
|
||||
text-align:right;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript" language="JavaScript">
|
||||
var TestCases = new Array();
|
||||
var cur;
|
||||
<xsl:for-each select="./testsuite">
|
||||
<xsl:apply-templates select="properties"/>
|
||||
</xsl:for-each>
|
||||
|
||||
</script>
|
||||
<script type="text/javascript" language="JavaScript"><![CDATA[
|
||||
function displayProperties (name) {
|
||||
var win = window.open('','JUnitSystemProperties','scrollbars=1,resizable=1');
|
||||
var doc = win.document;
|
||||
doc.open();
|
||||
doc.write("<html><head><title>Properties of " + name + "</title>");
|
||||
doc.write("<style>")
|
||||
doc.write("body {font:normal 68% verdana,arial,helvetica; color:#000000; }");
|
||||
doc.write("table tr td, table tr th { font-size: 68%; }");
|
||||
doc.write("table.properties { border-collapse:collapse; border-left:solid 1 #cccccc; border-top:solid 1 #cccccc; padding:5px; }");
|
||||
doc.write("table.properties th { text-align:left; border-right:solid 1 #cccccc; border-bottom:solid 1 #cccccc; background-color:#eeeeee; }");
|
||||
doc.write("table.properties td { font:normal; text-align:left; border-right:solid 1 #cccccc; border-bottom:solid 1 #cccccc; background-color:#fffffff; }");
|
||||
doc.write("h3 { margin-bottom: 0.5em; font: bold 115% verdana,arial,helvetica }");
|
||||
doc.write("</style>");
|
||||
doc.write("</head><body>");
|
||||
doc.write("<h3>Properties of " + name + "</h3>");
|
||||
doc.write("<div align=\"right\"><a href=\"javascript:window.close();\">Close</a></div>");
|
||||
doc.write("<table class='properties'>");
|
||||
doc.write("<tr><th>Name</th><th>Value</th></tr>");
|
||||
for (prop in TestCases[name]) {
|
||||
doc.write("<tr><th>" + prop + "</th><td>" + TestCases[name][prop] + "</td></tr>");
|
||||
}
|
||||
doc.write("</table>");
|
||||
doc.write("</body></html>");
|
||||
doc.close();
|
||||
win.focus();
|
||||
}
|
||||
]]>
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a name="top"></a>
|
||||
<xsl:call-template name="pageHeader"/>
|
||||
|
||||
<!-- Summary part -->
|
||||
<xsl:call-template name="summary"/>
|
||||
<hr size="1" width="95%" align="left"/>
|
||||
|
||||
<!-- Package List part -->
|
||||
<xsl:call-template name="packagelist"/>
|
||||
<hr size="1" width="95%" align="left"/>
|
||||
|
||||
<!-- For each package create its part -->
|
||||
<xsl:call-template name="packages"/>
|
||||
<hr size="1" width="95%" align="left"/>
|
||||
|
||||
<!-- For each class create the part -->
|
||||
<xsl:call-template name="classes"/>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
|
||||
<!-- ================================================================== -->
|
||||
<!-- Write a list of all packages with an hyperlink to the anchor of -->
|
||||
<!-- of the package name. -->
|
||||
<!-- ================================================================== -->
|
||||
<xsl:template name="packagelist">
|
||||
<h2>Packages</h2>
|
||||
Note: package statistics are not computed recursively, they only sum up all of its testsuites numbers.
|
||||
<table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
|
||||
<xsl:call-template name="testsuite.test.header"/>
|
||||
<!-- list all packages recursively -->
|
||||
<xsl:for-each select="./testsuite[not(./@package = preceding-sibling::testsuite/@package)]">
|
||||
<xsl:sort select="@package"/>
|
||||
<xsl:variable name="testsuites-in-package" select="/testsuites/testsuite[./@package = current()/@package]"/>
|
||||
<xsl:variable name="testCount" select="sum($testsuites-in-package/@tests)"/>
|
||||
<xsl:variable name="errorCount" select="sum($testsuites-in-package/@errors)"/>
|
||||
<xsl:variable name="failureCount" select="sum($testsuites-in-package/@failures)"/>
|
||||
<xsl:variable name="timeCount" select="sum($testsuites-in-package/@time)"/>
|
||||
|
||||
<!-- write a summary for the package -->
|
||||
<tr valign="top">
|
||||
<!-- set a nice color depending if there is an error/failure -->
|
||||
<xsl:attribute name="class">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$failureCount > 0">Failure</xsl:when>
|
||||
<xsl:when test="$errorCount > 0">Error</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<td><a href="#{@package}"><xsl:value-of select="@package"/></a></td>
|
||||
<td><xsl:value-of select="$testCount"/></td>
|
||||
<td><xsl:value-of select="$errorCount"/></td>
|
||||
<td><xsl:value-of select="$failureCount"/></td>
|
||||
<td>
|
||||
<xsl:call-template name="display-time">
|
||||
<xsl:with-param name="value" select="$timeCount"/>
|
||||
</xsl:call-template>
|
||||
</td>
|
||||
<td><xsl:value-of select="$testsuites-in-package/@timestamp"/></td>
|
||||
<td><xsl:value-of select="$testsuites-in-package/@hostname"/></td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
</table>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!-- ================================================================== -->
|
||||
<!-- Write a package level report -->
|
||||
<!-- It creates a table with values from the document: -->
|
||||
<!-- Name | Tests | Errors | Failures | Time -->
|
||||
<!-- ================================================================== -->
|
||||
<xsl:template name="packages">
|
||||
<!-- create an anchor to this package name -->
|
||||
<xsl:for-each select="/testsuites/testsuite[not(./@package = preceding-sibling::testsuite/@package)]">
|
||||
<xsl:sort select="@package"/>
|
||||
<a name="{@package}"></a>
|
||||
<h3>Package <xsl:value-of select="@package"/></h3>
|
||||
|
||||
<table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
|
||||
<xsl:call-template name="testsuite.test.header"/>
|
||||
|
||||
<!-- match the testsuites of this package -->
|
||||
<xsl:apply-templates select="/testsuites/testsuite[./@package = current()/@package]" mode="print.test"/>
|
||||
</table>
|
||||
<a href="#top">Back to top</a>
|
||||
<p/>
|
||||
<p/>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="classes">
|
||||
<xsl:for-each select="testsuite">
|
||||
<xsl:sort select="@name"/>
|
||||
<!-- create an anchor to this class name -->
|
||||
<a name="{@name}"></a>
|
||||
<h3>TestCase <xsl:value-of select="@name"/></h3>
|
||||
|
||||
<table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
|
||||
<xsl:call-template name="testcase.test.header"/>
|
||||
<!--
|
||||
test can even not be started at all (failure to load the class)
|
||||
so report the error directly
|
||||
-->
|
||||
<xsl:if test="./error">
|
||||
<tr class="Error">
|
||||
<td colspan="4"><xsl:apply-templates select="./error"/></td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates select="./testcase" mode="print.test"/>
|
||||
</table>
|
||||
<div class="Properties">
|
||||
<a>
|
||||
<xsl:attribute name="href">javascript:displayProperties('<xsl:value-of select="@package"/>.<xsl:value-of select="@name"/>');</xsl:attribute>
|
||||
Properties »
|
||||
</a>
|
||||
</div>
|
||||
<p/>
|
||||
|
||||
<a href="#top">Back to top</a>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="summary">
|
||||
<h2>Summary</h2>
|
||||
<xsl:variable name="testCount" select="sum(testsuite/@tests)"/>
|
||||
<xsl:variable name="errorCount" select="sum(testsuite/@errors)"/>
|
||||
<xsl:variable name="failureCount" select="sum(testsuite/@failures)"/>
|
||||
<xsl:variable name="timeCount" select="sum(testsuite/@time)"/>
|
||||
<xsl:variable name="successRate" select="($testCount - $failureCount - $errorCount) div $testCount"/>
|
||||
<table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
|
||||
<tr valign="top">
|
||||
<th>Tests</th>
|
||||
<th>Failures</th>
|
||||
<th>Errors</th>
|
||||
<th>Success rate</th>
|
||||
<th>Time</th>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<xsl:attribute name="class">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$failureCount > 0">Failure</xsl:when>
|
||||
<xsl:when test="$errorCount > 0">Error</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<td><xsl:value-of select="$testCount"/></td>
|
||||
<td><xsl:value-of select="$failureCount"/></td>
|
||||
<td><xsl:value-of select="$errorCount"/></td>
|
||||
<td>
|
||||
<xsl:call-template name="display-percent">
|
||||
<xsl:with-param name="value" select="$successRate"/>
|
||||
</xsl:call-template>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:call-template name="display-time">
|
||||
<xsl:with-param name="value" select="$timeCount"/>
|
||||
</xsl:call-template>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
<table border="0" width="95%">
|
||||
<tr>
|
||||
<td style="text-align: justify;">
|
||||
Note: <i>failures</i> are anticipated and checked for with assertions while <i>errors</i> are unanticipated.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Write properties into a JavaScript data structure.
|
||||
This is based on the original idea by Erik Hatcher (ehatcher@apache.org)
|
||||
-->
|
||||
<xsl:template match="properties">
|
||||
cur = TestCases['<xsl:value-of select="../@package"/>.<xsl:value-of select="../@name"/>'] = new Array();
|
||||
<xsl:for-each select="property">
|
||||
<xsl:sort select="@name"/>
|
||||
cur['<xsl:value-of select="@name"/>'] = '<xsl:call-template name="JS-escape"><xsl:with-param name="string" select="@value"/></xsl:call-template>';
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Page HEADER -->
|
||||
<xsl:template name="pageHeader">
|
||||
<h1><xsl:value-of select="$TITLE"/></h1>
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td align="left"></td>
|
||||
<td align="right">Designed for use with <a href='http://www.junit.org'>JUnit</a> and <a href='http://ant.apache.org/ant'>Ant</a>.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr size="1"/>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="testsuite" mode="header">
|
||||
<tr valign="top">
|
||||
<th width="80%">Name</th>
|
||||
<th>Tests</th>
|
||||
<th>Errors</th>
|
||||
<th>Failures</th>
|
||||
<th nowrap="nowrap">Time(s)</th>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
|
||||
<!-- class header -->
|
||||
<xsl:template name="testsuite.test.header">
|
||||
<tr valign="top">
|
||||
<th width="80%">Name</th>
|
||||
<th>Tests</th>
|
||||
<th>Errors</th>
|
||||
<th>Failures</th>
|
||||
<th nowrap="nowrap">Time(s)</th>
|
||||
<th nowrap="nowrap">Time Stamp</th>
|
||||
<th>Host</th>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
|
||||
<!-- method header -->
|
||||
<xsl:template name="testcase.test.header">
|
||||
<tr valign="top">
|
||||
<th>Name</th>
|
||||
<th>Status</th>
|
||||
<th width="80%">Type</th>
|
||||
<th nowrap="nowrap">Time(s)</th>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!-- class information -->
|
||||
<xsl:template match="testsuite" mode="print.test">
|
||||
<tr valign="top">
|
||||
<!-- set a nice color depending if there is an error/failure -->
|
||||
<xsl:attribute name="class">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@failures[.> 0]">Failure</xsl:when>
|
||||
<xsl:when test="@errors[.> 0]">Error</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
|
||||
<!-- print testsuite information -->
|
||||
<td><a href="#{@name}"><xsl:value-of select="@name"/></a></td>
|
||||
<td><xsl:value-of select="@tests"/></td>
|
||||
<td><xsl:value-of select="@errors"/></td>
|
||||
<td><xsl:value-of select="@failures"/></td>
|
||||
<td>
|
||||
<xsl:call-template name="display-time">
|
||||
<xsl:with-param name="value" select="@time"/>
|
||||
</xsl:call-template>
|
||||
</td>
|
||||
<td><xsl:apply-templates select="@timestamp"/></td>
|
||||
<td><xsl:apply-templates select="@hostname"/></td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="testcase" mode="print.test">
|
||||
<tr valign="top">
|
||||
<xsl:attribute name="class">
|
||||
<xsl:choose>
|
||||
<xsl:when test="failure | error">Error</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<td><xsl:value-of select="@name"/></td>
|
||||
<xsl:choose>
|
||||
<xsl:when test="failure">
|
||||
<td>Failure</td>
|
||||
<td><xsl:apply-templates select="failure"/></td>
|
||||
</xsl:when>
|
||||
<xsl:when test="error">
|
||||
<td>Error</td>
|
||||
<td><xsl:apply-templates select="error"/></td>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<td>Success</td>
|
||||
<td></td>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<td>
|
||||
<xsl:call-template name="display-time">
|
||||
<xsl:with-param name="value" select="@time"/>
|
||||
</xsl:call-template>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="failure">
|
||||
<xsl:call-template name="display-failures"/>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="error">
|
||||
<xsl:call-template name="display-failures"/>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Style for the error and failure in the tescase template -->
|
||||
<xsl:template name="display-failures">
|
||||
<xsl:choose>
|
||||
<xsl:when test="not(@message)">N/A</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="@message"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<!-- display the stacktrace -->
|
||||
<code>
|
||||
<br/><br/>
|
||||
<xsl:call-template name="br-replace">
|
||||
<xsl:with-param name="word" select="."/>
|
||||
</xsl:call-template>
|
||||
</code>
|
||||
<!-- the later is better but might be problematic for non-21" monitors... -->
|
||||
<!--pre><xsl:value-of select="."/></pre-->
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="JS-escape">
|
||||
<xsl:param name="string"/>
|
||||
<xsl:param name="tmp1" select="stringutils:replace(string($string),'\','\\')"/>
|
||||
<xsl:param name="tmp2" select="stringutils:replace(string($tmp1),"'","\'")"/>
|
||||
<xsl:value-of select="$tmp2"/>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!--
|
||||
template that will convert a carriage return into a br tag
|
||||
@param word the text from which to convert CR to BR tag
|
||||
-->
|
||||
<xsl:template name="br-replace">
|
||||
<xsl:param name="word"/>
|
||||
<xsl:value-of disable-output-escaping="yes" select='stringutils:replace(string($word),"
","<br/>")'/>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="display-time">
|
||||
<xsl:param name="value"/>
|
||||
<xsl:value-of select="format-number($value,'0.000')"/>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="display-percent">
|
||||
<xsl:param name="value"/>
|
||||
<xsl:value-of select="format-number($value,'0.00%')"/>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
@@ -11,7 +11,6 @@
|
||||
<orderEntry type="module" module-name="lang-impl" />
|
||||
<orderEntry type="module" module-name="platform-impl" />
|
||||
<orderEntry type="module" module-name="xdebugger-api" />
|
||||
<orderEntry type="library" name="Ant" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -510,7 +510,7 @@ public class FileUtil {
|
||||
return parentFile.exists() && parentFile.isDirectory() || parentFile.mkdirs();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean createIfDoesntExist(File file) {
|
||||
|
||||
@@ -1236,6 +1236,20 @@ public class StringUtil {
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to answer if target symbol is contained at given char sequence at <code>[start; end)</code> interval.
|
||||
*
|
||||
* @param s target char sequence to check
|
||||
* @param start start offset to use within the given char sequence (inclusive)
|
||||
* @param end end offset to use within the given char sequence (exclusive)
|
||||
* @param c target symbol to check
|
||||
* @return <code>true</code> if given symbol is contained at the target range of the given char sequence;
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
public static boolean contains(CharSequence s, int start, int end, char c) {
|
||||
return indexOf(s, c, start, end) >= 0;
|
||||
}
|
||||
|
||||
public static int indexOf(@NotNull CharSequence s, char c) {
|
||||
return indexOf(s, c, 0, s.length());
|
||||
}
|
||||
|
||||
+1
-1
@@ -163,7 +163,7 @@ public class IncomingChangesIndicator implements ProjectComponent {
|
||||
return "IncomingChanges";
|
||||
}
|
||||
|
||||
public WidgetPresentation getPresentation(@NotNull Type type) {
|
||||
public WidgetPresentation getPresentation(@NotNull PlatformType type) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -174,7 +174,7 @@ public class IOResourceInspection extends ResourceInspection {
|
||||
public boolean isIOResource(PsiExpression expression){
|
||||
return TypeUtils.expressionHasTypeOrSubtype(expression,
|
||||
"java.io.InputStream", "java.io.Writer", "java.io.Reader",
|
||||
"java.io.RandomAccessFile", "java.io.OutputStream") != null &&
|
||||
"java.io.RandomAccessFile", "java.io.OutputStream", "java.util.zip.ZipFile") != null &&
|
||||
!isIgnoredType(expression);
|
||||
}
|
||||
|
||||
|
||||
@@ -207,6 +207,11 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
|
||||
* The reference tracker
|
||||
*/
|
||||
private GitReferenceTracker myReferenceTracker;
|
||||
/**
|
||||
* If true, the vcs was activated
|
||||
*/
|
||||
private boolean isActivated;
|
||||
|
||||
|
||||
public static GitVcs getInstance(@NotNull Project project) {
|
||||
return (GitVcs)ProjectLevelVcsManager.getInstance(project).findVcsByName(NAME);
|
||||
@@ -496,6 +501,7 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
|
||||
*/
|
||||
@Override
|
||||
protected void activate() {
|
||||
isActivated = true;
|
||||
if (!myProject.isDefault() && myRootTracker == null) {
|
||||
myRootTracker = new GitRootTracker(this, myProject, myRootListeners.getMulticaster());
|
||||
}
|
||||
@@ -519,6 +525,7 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
|
||||
*/
|
||||
@Override
|
||||
protected void deactivate() {
|
||||
isActivated = false;
|
||||
GitBranchConfigurations.getInstance(myProject).deactivate();
|
||||
if (myRootTracker != null) {
|
||||
myRootTracker.dispose();
|
||||
@@ -768,4 +775,11 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
|
||||
final VirtualFile vcsRoot = GitUtil.getGitRoot(file);
|
||||
return GitChangeUtils.getRevisionChanges(project, vcsRoot, revision.getRevisionNumber().asString(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if vcs was activated
|
||||
*/
|
||||
public boolean isActivated() {
|
||||
return isActivated;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ public class GitPushActiveBranchesDialog extends DialogWrapper {
|
||||
if (seenMerges) {
|
||||
rootsWithMerges.add(r.root);
|
||||
}
|
||||
if (r.remoteCommits > 0 && seenCheckedNode || reorderNeeded) {
|
||||
if (r.remoteCommits > 0 || reorderNeeded) {
|
||||
roots.add(r.root);
|
||||
}
|
||||
if (reorderNeeded) {
|
||||
|
||||
+4
-3
@@ -89,7 +89,7 @@ public class GitBranchConfigurationChangedDialog extends DialogWrapper {
|
||||
myTable.setModel(new DescriptorTableModel());
|
||||
myNameTextField.setText(config.getName());
|
||||
myNewAction = new DialogWrapperExitAction("New Configuration", NEW_CONFIGURATION);
|
||||
myNameTextField.getDocument().addDocumentListener(new DocumentAdapter() {
|
||||
final DocumentAdapter l = new DocumentAdapter() {
|
||||
@Override
|
||||
protected void textChanged(DocumentEvent e) {
|
||||
String text = myNameTextField.getText().trim();
|
||||
@@ -113,8 +113,9 @@ public class GitBranchConfigurationChangedDialog extends DialogWrapper {
|
||||
setOKActionEnabled(s == null);
|
||||
myNewAction.setEnabled(s == null);
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
myNameTextField.getDocument().addDocumentListener(l);
|
||||
l.changedUpdate(null);
|
||||
setOKButtonText("Update");
|
||||
init();
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ import git4idea.vfs.GitReferenceListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@@ -147,6 +148,10 @@ public class GitBranchConfigurations implements PersistentStateComponent<GitBran
|
||||
* Listener for changes
|
||||
*/
|
||||
private final ChangeListAdapter myChangesListener;
|
||||
/**
|
||||
* If true, the widget is enabled
|
||||
*/
|
||||
private boolean myWidgetEnabled = true;
|
||||
|
||||
/**
|
||||
* The constructor used to dependency injection
|
||||
@@ -268,8 +273,20 @@ public class GitBranchConfigurations implements PersistentStateComponent<GitBran
|
||||
}
|
||||
referencesChanged();
|
||||
}
|
||||
if (isWidgetEnabled()) {
|
||||
installWidget();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Install widget
|
||||
*/
|
||||
private void installWidget() {
|
||||
if (!ApplicationManager.getApplication().isHeadlessEnvironment()) {
|
||||
myWidgetUninstall = GitBranchesWidget.install(myProject, this);
|
||||
final Runnable r = GitBranchesWidget.install(myProject, this);
|
||||
synchronized (myStateLock) {
|
||||
myWidgetUninstall = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,10 +296,18 @@ public class GitBranchConfigurations implements PersistentStateComponent<GitBran
|
||||
public void deactivate() {
|
||||
myVcs.removeGitReferenceListener(myReferenceListener);
|
||||
myChangeManager.removeChangeListListener(myChangesListener);
|
||||
if (myWidgetUninstall != null) {
|
||||
myWidgetUninstall.run();
|
||||
uninstallWidget();
|
||||
}
|
||||
|
||||
private void uninstallWidget() {
|
||||
final Runnable r;
|
||||
synchronized (myStateLock) {
|
||||
r = myWidgetUninstall;
|
||||
myWidgetUninstall = null;
|
||||
}
|
||||
if (r != null) {
|
||||
r.run();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -310,6 +335,7 @@ public class GitBranchConfigurations implements PersistentStateComponent<GitBran
|
||||
public State getState() {
|
||||
synchronized (myStateLock) {
|
||||
State rc = new State();
|
||||
rc.IS_WIDGET_ENABLED = myWidgetEnabled;
|
||||
rc.CURRENT = myCurrentConfiguration == null ? null : myCurrentConfiguration.getName();
|
||||
ArrayList<BranchConfiguration> cs = new ArrayList<BranchConfiguration>(myConfigurations.size());
|
||||
for (GitBranchConfiguration ci : myConfigurations.values()) {
|
||||
@@ -363,9 +389,54 @@ public class GitBranchConfigurations implements PersistentStateComponent<GitBran
|
||||
}
|
||||
fireCurrentConfigurationChanged();
|
||||
fireConfigurationsChanged();
|
||||
if (state.IS_WIDGET_ENABLED != myWidgetEnabled) {
|
||||
myWidgetEnabled = state.IS_WIDGET_ENABLED;
|
||||
updateWidgetState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update widget state after update
|
||||
*/
|
||||
private void updateWidgetState() {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (isWidgetEnabled()) {
|
||||
if (myVcs.isActivated() && myWidgetUninstall == null) {
|
||||
installWidget();
|
||||
}
|
||||
}
|
||||
else {
|
||||
uninstallWidget();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if widget is enabled
|
||||
*/
|
||||
public boolean isWidgetEnabled() {
|
||||
synchronized (myStateLock) {
|
||||
return myWidgetEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update widget state
|
||||
*
|
||||
* @param value true to enable widget
|
||||
*/
|
||||
public void setWidgetEnabled(boolean value) {
|
||||
synchronized (myStateLock) {
|
||||
myWidgetEnabled = value;
|
||||
updateWidgetState();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the candidate remote configurations
|
||||
*/
|
||||
@@ -632,18 +703,6 @@ public class GitBranchConfigurations implements PersistentStateComponent<GitBran
|
||||
return myStateLock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if configuration with specified name already exists
|
||||
*
|
||||
* @param name the name to check
|
||||
* @return true if the configuration exists
|
||||
*/
|
||||
boolean hasConfigurationName(String name) {
|
||||
synchronized (myStateLock) {
|
||||
return myConfigurations.containsKey(name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set current configuration
|
||||
*
|
||||
@@ -765,6 +824,10 @@ public class GitBranchConfigurations implements PersistentStateComponent<GitBran
|
||||
* The configuration state
|
||||
*/
|
||||
public static class State {
|
||||
/**
|
||||
* If true, branches widget is enabled
|
||||
*/
|
||||
public boolean IS_WIDGET_ENABLED = true;
|
||||
/**
|
||||
* The current configuration
|
||||
*/
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
@@ -29,6 +30,7 @@ import com.intellij.openapi.ui.popup.ListPopup;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.changes.ui.ChangesViewContentManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -36,6 +38,7 @@ import com.intellij.openapi.wm.CustomStatusBarWidget;
|
||||
import com.intellij.openapi.wm.StatusBar;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.openapi.wm.impl.status.TextPanel;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import git4idea.GitUtil;
|
||||
@@ -57,12 +60,15 @@ import java.util.Collection;
|
||||
/**
|
||||
* The git branches widget
|
||||
*/
|
||||
public class GitBranchesWidget extends JLabel implements CustomStatusBarWidget {
|
||||
public class GitBranchesWidget extends TextPanel implements CustomStatusBarWidget {
|
||||
/**
|
||||
* The arrows icon
|
||||
*/
|
||||
private static final Icon ARROWS_ICON = IconLoader.getIcon("/ide/statusbar_arrows.png");
|
||||
/**
|
||||
* The logger
|
||||
*/
|
||||
private static final Logger LOG = Logger.getInstance(GitBranchesWidget.class.getName());
|
||||
|
||||
/**
|
||||
* The ID of the widget
|
||||
*/
|
||||
@@ -75,6 +81,10 @@ public class GitBranchesWidget extends JLabel implements CustomStatusBarWidget {
|
||||
* The project
|
||||
*/
|
||||
final Project myProject;
|
||||
/**
|
||||
* The status bar
|
||||
*/
|
||||
private final StatusBar myStatusBar;
|
||||
/**
|
||||
* The configurations instance
|
||||
*/
|
||||
@@ -83,14 +93,14 @@ public class GitBranchesWidget extends JLabel implements CustomStatusBarWidget {
|
||||
* The selectable configurations. Null if invalidated or non-initialized
|
||||
*/
|
||||
private AnAction[] mySelectableConfigurations;
|
||||
/**
|
||||
* The selectable configurations. Null if invalidated or non-initialized
|
||||
*/
|
||||
private AnAction[] mySelectableWithChangesConfigurations;
|
||||
/**
|
||||
* The candidate remote configurations. Null if invalidated or non-initialized
|
||||
*/
|
||||
private AnAction[] myRemoveConfigurations;
|
||||
/**
|
||||
* The status bar
|
||||
*/
|
||||
private StatusBar myStatusBar;
|
||||
/**
|
||||
* If true, the popup is enabled
|
||||
*/
|
||||
@@ -103,6 +113,10 @@ public class GitBranchesWidget extends JLabel implements CustomStatusBarWidget {
|
||||
* The current popup
|
||||
*/
|
||||
private ListPopup myPopup;
|
||||
/**
|
||||
* The key for the last popup, used to determine if disposed popup is the actually the last pop up.
|
||||
*/
|
||||
private Object myPopupKey;
|
||||
/**
|
||||
* The default foreground color
|
||||
*/
|
||||
@@ -112,17 +126,18 @@ public class GitBranchesWidget extends JLabel implements CustomStatusBarWidget {
|
||||
/**
|
||||
* The constructor
|
||||
*
|
||||
* @param project the project instance
|
||||
* @param project the project instance
|
||||
* @param statusBar the status bar
|
||||
* @param configurations the configuration settings
|
||||
*/
|
||||
public GitBranchesWidget(Project project, GitBranchConfigurations configurations) {
|
||||
public GitBranchesWidget(Project project, StatusBar statusBar, GitBranchConfigurations configurations) {
|
||||
myProject = project;
|
||||
myStatusBar = statusBar;
|
||||
setBorder(WidgetBorder.INSTANCE);
|
||||
//setBorder(BorderFactory.createEtchedBorder());
|
||||
myConfigurations = configurations;
|
||||
myDefaultForeground = getForeground();
|
||||
myConfigurationsListener = new MyGitBranchConfigurationsListener();
|
||||
myConfigurations.addConfigurationListener(myConfigurationsListener);
|
||||
setIcon(IconLoader.findIcon("/icons/branch.png", getClass()));
|
||||
Disposer.register(myConfigurations, this);
|
||||
addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
@@ -147,8 +162,8 @@ public class GitBranchesWidget extends JLabel implements CustomStatusBarWidget {
|
||||
public void run() {
|
||||
StatusBar statusBar = WindowManager.getInstance().getStatusBar(project);
|
||||
if (statusBar != null) {
|
||||
final GitBranchesWidget w = new GitBranchesWidget(project, configurations);
|
||||
statusBar.addWidget(w, "after InsertOverwrite", project);
|
||||
final GitBranchesWidget w = new GitBranchesWidget(project, statusBar, configurations);
|
||||
statusBar.addWidget(w, "after " + (SystemInfo.isMac ? "Encoding" : "InsertOverwrite"), project);
|
||||
widget.set(w);
|
||||
}
|
||||
}
|
||||
@@ -190,7 +205,7 @@ public class GitBranchesWidget extends JLabel implements CustomStatusBarWidget {
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public WidgetPresentation getPresentation(@NotNull Type type) {
|
||||
public WidgetPresentation getPresentation(@NotNull PlatformType type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -199,7 +214,6 @@ public class GitBranchesWidget extends JLabel implements CustomStatusBarWidget {
|
||||
*/
|
||||
@Override
|
||||
public void install(@NotNull StatusBar statusBar) {
|
||||
myStatusBar = statusBar;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -219,7 +233,7 @@ public class GitBranchesWidget extends JLabel implements CustomStatusBarWidget {
|
||||
if (myRemoveConfigurations == null) {
|
||||
ArrayList<AnAction> rc = new ArrayList<AnAction>();
|
||||
for (final String c : myConfigurations.getRemotesCandidates()) {
|
||||
rc.add(new AnAction(c) {
|
||||
rc.add(new DumbAwareAction(c) {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
myConfigurations.startCheckout(null, c, false);
|
||||
@@ -232,19 +246,28 @@ public class GitBranchesWidget extends JLabel implements CustomStatusBarWidget {
|
||||
return myRemoveConfigurations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show popup is if it is not shown.
|
||||
*/
|
||||
void showPopup() {
|
||||
if (!myPopupEnabled) {
|
||||
return;
|
||||
}
|
||||
if (myPopup != null) {
|
||||
myPopup.cancel();
|
||||
}
|
||||
final DataContext parent = DataManager.getInstance().getDataContext((Component)myStatusBar);
|
||||
final DataContext dataContext = SimpleDataContext.getSimpleContext(PlatformDataKeys.PROJECT.getName(), myProject, parent);
|
||||
final Object key = new Object();
|
||||
myPopupKey = key;
|
||||
myPopup = JBPopupFactory.getInstance()
|
||||
.createActionGroupPopup("Checkout", getPopupActionGroup(), dataContext, JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, true,
|
||||
.createActionGroupPopup(null, getPopupActionGroup(), dataContext, JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, true,
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myPopup = null;
|
||||
|
||||
if (key == myPopupKey) {
|
||||
myPopup = null;
|
||||
}
|
||||
}
|
||||
}, 20);
|
||||
final Dimension dimension = myPopup.getContent().getPreferredSize();
|
||||
@@ -253,13 +276,13 @@ public class GitBranchesWidget extends JLabel implements CustomStatusBarWidget {
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that action for checking out configurations are crated
|
||||
*
|
||||
* @return get or create selectable configuration group
|
||||
*/
|
||||
private AnAction[] getSelectable() {
|
||||
private AnAction[] ensureSelectableCreated() {
|
||||
assert myPopupEnabled : "pop should be enabled";
|
||||
if (mySelectableConfigurations == null) {
|
||||
ArrayList<AnAction> rc = new ArrayList<AnAction>();
|
||||
|
||||
if (mySelectableConfigurations == null || mySelectableWithChangesConfigurations == null) {
|
||||
GitBranchConfiguration current;
|
||||
try {
|
||||
current = myConfigurations.getCurrentConfiguration();
|
||||
@@ -267,48 +290,63 @@ public class GitBranchesWidget extends JLabel implements CustomStatusBarWidget {
|
||||
catch (VcsException e) {
|
||||
LOG.error("Unexpected error at this point", e);
|
||||
mySelectableConfigurations = new AnAction[0];
|
||||
mySelectableWithChangesConfigurations = new AnAction[0];
|
||||
|
||||
return mySelectableConfigurations;
|
||||
}
|
||||
String name = current == null ? "" : current.getName();
|
||||
for (final String c : myConfigurations.getConfigurationNames()) {
|
||||
if (name.equals(c)) {
|
||||
// skip current config
|
||||
continue;
|
||||
}
|
||||
rc.add(new AnAction(c) {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
try {
|
||||
final GitBranchConfiguration toCheckout = myConfigurations.getConfiguration(c);
|
||||
if (toCheckout == null) {
|
||||
throw new VcsException("The configuration " + c + " cannot be found.");
|
||||
}
|
||||
myConfigurations.startCheckout(toCheckout, null, true);
|
||||
}
|
||||
catch (VcsException e1) {
|
||||
GitUIUtil.showOperationError(myProject, e1, "Unable to load: " + c);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
mySelectableConfigurations = rc.toArray(new AnAction[rc.size()]);
|
||||
mySelectableConfigurations = checkoutActions(name, true);
|
||||
mySelectableWithChangesConfigurations = checkoutActions(name, false);
|
||||
}
|
||||
return mySelectableConfigurations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checkout actions
|
||||
*
|
||||
* @param name the excluded name
|
||||
* @param quick true, if quick checkout actions
|
||||
* @return an array of actions for the configurations
|
||||
*/
|
||||
private AnAction[] checkoutActions(String name, final boolean quick) {
|
||||
ArrayList<AnAction> rc = new ArrayList<AnAction>();
|
||||
for (final String c : myConfigurations.getConfigurationNames()) {
|
||||
if (name.equals(c)) {
|
||||
// skip current config
|
||||
continue;
|
||||
}
|
||||
rc.add(new DumbAwareAction(c) {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
try {
|
||||
final GitBranchConfiguration toCheckout = myConfigurations.getConfiguration(c);
|
||||
if (toCheckout == null) {
|
||||
throw new VcsException("The configuration " + c + " cannot be found.");
|
||||
}
|
||||
myConfigurations.startCheckout(toCheckout, null, quick);
|
||||
}
|
||||
catch (VcsException e1) {
|
||||
GitUIUtil.showOperationError(myProject, e1, "Unable to load: " + c);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return rc.toArray(new AnAction[rc.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the action group for popup
|
||||
*/
|
||||
ActionGroup getPopupActionGroup() {
|
||||
if (myPopupActionGroup == null) {
|
||||
myPopupActionGroup = new DefaultActionGroup(null, false);
|
||||
myPopupActionGroup.addAction(new AnAction("Manage Configurations ...") {
|
||||
myPopupActionGroup.addAction(new DumbAwareAction("Manage Configurations ...") {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
GitManageConfigurationsDialog.showDialog(myProject, myConfigurations);
|
||||
}
|
||||
});
|
||||
myPopupActionGroup.addAction(new AnAction("Modify Current Configuration ...") {
|
||||
myPopupActionGroup.addAction(new DumbAwareAction("Modify Current Configuration ...") {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
try {
|
||||
@@ -320,13 +358,14 @@ public class GitBranchesWidget extends JLabel implements CustomStatusBarWidget {
|
||||
}
|
||||
}
|
||||
});
|
||||
myPopupActionGroup.addAction(new AnAction("New Configuration ...") {
|
||||
myPopupActionGroup.addAction(new DumbAwareAction("New Configuration ...") {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
myConfigurations.startCheckout(null, null, false);
|
||||
}
|
||||
});
|
||||
myPopupActionGroup.add(new MyRemotesActionGroup());
|
||||
myPopupActionGroup.add(new MySelectableWithChangesActionGroup());
|
||||
myPopupActionGroup.addSeparator("Branch Configurations");
|
||||
myPopupActionGroup.add(new MySelectableActionGroup());
|
||||
}
|
||||
@@ -339,23 +378,32 @@ public class GitBranchesWidget extends JLabel implements CustomStatusBarWidget {
|
||||
private void updateLabel() {
|
||||
cancelPopup();
|
||||
final GitBranchConfigurations.SpecialStatus status = myConfigurations.getSpecialStatus();
|
||||
String t;
|
||||
String text;
|
||||
myPopupEnabled = false;
|
||||
Color color = Color.RED;
|
||||
String tooltip;
|
||||
switch (status) {
|
||||
case CHECKOUT_IN_PROGRESS:
|
||||
t = "Checkout in progress...";
|
||||
text = "Checkout...";
|
||||
color = Color.BLUE;
|
||||
tooltip = "A checkout operation is in progress.";
|
||||
break;
|
||||
case MERGING:
|
||||
t = "Merging...";
|
||||
text = "Merging...";
|
||||
tooltip = "Merge is in progress in some vcs roots.";
|
||||
break;
|
||||
case REBASING:
|
||||
t = "Rebasing...";
|
||||
tooltip = "Rebase is in progress in some vcs roots.";
|
||||
text = "Rebasing...";
|
||||
break;
|
||||
case NON_GIT:
|
||||
t = "Non-Git project";
|
||||
tooltip = "No valid vcs roots are configuration for the project.";
|
||||
text = "Non-Git project";
|
||||
break;
|
||||
case SUBMODULES:
|
||||
t = "Submodules unsupported";
|
||||
tooltip =
|
||||
"<html>The submodules are unsupported in the current version.<br/>It is possible to disable widget in Git Vcs settings.</html>";
|
||||
text = "Submodules unsupported";
|
||||
break;
|
||||
case NORMAL:
|
||||
GitBranchConfiguration current;
|
||||
@@ -366,18 +414,49 @@ public class GitBranchesWidget extends JLabel implements CustomStatusBarWidget {
|
||||
current = null;
|
||||
}
|
||||
if (current == null) {
|
||||
t = "Detection in progress";
|
||||
tooltip = "The branch configurations are not yet detected.";
|
||||
text = "Detecting...";
|
||||
}
|
||||
else {
|
||||
myPopupEnabled = true;
|
||||
t = current.getName();
|
||||
text = current.getName();
|
||||
tooltip = "<html>The Git branch configuration <b>" + text + "</b> is selected.<br/>Click to select other configuration.</html>";
|
||||
color = myDefaultForeground;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
t = "Unknown status: " + status;
|
||||
tooltip = "Unknown status: " + status;
|
||||
text = "Unknown status: " + status;
|
||||
}
|
||||
setForeground(myPopupEnabled ? myDefaultForeground : Color.RED);
|
||||
setText(t);
|
||||
if (!SystemInfo.isMac) {
|
||||
setForeground(color);
|
||||
}
|
||||
setToolTipText(tooltip);
|
||||
setText(text);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(@NotNull final Graphics g) {
|
||||
super.paintComponent(g);
|
||||
|
||||
if (getText() != null && myPopupEnabled) {
|
||||
final Rectangle r = getBounds();
|
||||
final Insets insets = getInsets();
|
||||
ARROWS_ICON
|
||||
.paintIcon(this, g, r.width - insets.right - ARROWS_ICON.getIconWidth() - 2, r.height / 2 - ARROWS_ICON.getIconHeight() / 2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
final Dimension preferredSize = super.getPreferredSize();
|
||||
return new Dimension(preferredSize.width + ARROWS_ICON.getIconWidth() + 4, preferredSize.height);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTextForPreferredSize() {
|
||||
return getText();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -406,7 +485,29 @@ public class GitBranchesWidget extends JLabel implements CustomStatusBarWidget {
|
||||
@NotNull
|
||||
@Override
|
||||
public AnAction[] getChildren(@Nullable AnActionEvent e) {
|
||||
return getSelectable();
|
||||
return ensureSelectableCreated();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remotes action group
|
||||
*/
|
||||
class MySelectableWithChangesActionGroup extends ActionGroup {
|
||||
/**
|
||||
* The constructor
|
||||
*/
|
||||
public MySelectableWithChangesActionGroup() {
|
||||
super("Check out with Selected Changes...", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@NotNull
|
||||
@Override
|
||||
public AnAction[] getChildren(@Nullable AnActionEvent e) {
|
||||
ensureSelectableCreated();
|
||||
return mySelectableWithChangesConfigurations;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,6 +545,7 @@ public class GitBranchesWidget extends JLabel implements CustomStatusBarWidget {
|
||||
@Override
|
||||
public void run() {
|
||||
mySelectableConfigurations = null;
|
||||
mySelectableWithChangesConfigurations = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -475,6 +577,7 @@ public class GitBranchesWidget extends JLabel implements CustomStatusBarWidget {
|
||||
@Override
|
||||
public void run() {
|
||||
mySelectableConfigurations = null;
|
||||
mySelectableWithChangesConfigurations = null;
|
||||
updateLabel();
|
||||
}
|
||||
});
|
||||
@@ -498,7 +601,7 @@ public class GitBranchesWidget extends JLabel implements CustomStatusBarWidget {
|
||||
/**
|
||||
* Refresh git remotes
|
||||
*/
|
||||
class RefreshRemotesAction extends AnAction {
|
||||
class RefreshRemotesAction extends DumbAwareAction {
|
||||
/**
|
||||
* The constructor
|
||||
*/
|
||||
@@ -549,5 +652,4 @@ public class GitBranchesWidget extends JLabel implements CustomStatusBarWidget {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -585,10 +585,7 @@ public class GitCheckoutProcess {
|
||||
LocalChangeList defaultList = myChangeManager.getDefaultChangeList();
|
||||
for (ChangeListInfo changeListInfo : changes.CHANGE_LISTS) {
|
||||
LocalChangeList changeList = lists.get(changeListInfo.NAME);
|
||||
if (changeList != null) {
|
||||
myChangeManager.setReadOnly(changeList.getName(), false);
|
||||
}
|
||||
else {
|
||||
if (changeList == null) {
|
||||
changeList = myChangeManager.addChangeList(changeListInfo.NAME, changeListInfo.COMMENT);
|
||||
lists.put(changeListInfo.NAME, changeList);
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ public class GitManageConfigurationsDialog extends DialogWrapper {
|
||||
"</td></tr></html>");
|
||||
}
|
||||
}
|
||||
boolean isNonCurrent = selected != null || selected != current;
|
||||
boolean isNonCurrent = selected != null && selected != current;
|
||||
myDeleteButton.setEnabled(isNonCurrent);
|
||||
setOKActionEnabled(isNonCurrent && myConfigurations.getSpecialStatus() == GitBranchConfigurations.SpecialStatus.NORMAL);
|
||||
}
|
||||
|
||||
@@ -205,6 +205,7 @@ public class GitSwitchBranchesDialog extends DialogWrapper {
|
||||
verify();
|
||||
}
|
||||
});
|
||||
verify();
|
||||
init();
|
||||
}
|
||||
|
||||
@@ -819,8 +820,7 @@ public class GitSwitchBranchesDialog extends DialogWrapper {
|
||||
@Override
|
||||
protected void textChanged(DocumentEvent e) {
|
||||
String s = myTextField.getText();
|
||||
if (s.length() == 0 &&
|
||||
(myInvalidValues == null || !myInvalidValues.contains(s)) &&
|
||||
if ((myInvalidValues == null || !myInvalidValues.contains(s)) &&
|
||||
(s.length() == 0 || GitBranchNameValidator.INSTANCE.checkInput(s))) {
|
||||
myTextField.setForeground(myDefaultForeground);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="git4idea.config.GitVcsPanel">
|
||||
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="6" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="500" height="400"/>
|
||||
@@ -10,107 +10,150 @@
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="b1a9d" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="git4idea/i18n/GitBundle" key="git.vcs.config.path.label"/>
|
||||
<verifyInputWhenFocusTarget value="false"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="25af7" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myGitField">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<vspacer id="4c83d">
|
||||
<constraints>
|
||||
<grid row="5" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<component id="563b2" class="javax.swing.JButton" binding="myTestButton">
|
||||
<constraints>
|
||||
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="2" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<horizontalAlignment value="0"/>
|
||||
<label resource-bundle="git4idea/i18n/GitBundle" key="git.vcs.config.test.label"/>
|
||||
<text resource-bundle="git4idea/i18n/GitBundle" key="git.vcs.config.test"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="5a909" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<labelFor value="f5de9"/>
|
||||
<text resource-bundle="git4idea/i18n/GitBundle" key="git.vcs.config.ssh.mode"/>
|
||||
</properties>
|
||||
</component>
|
||||
<grid id="97c7d" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="b95e2" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<border type="etched" title="Interface Options">
|
||||
<font/>
|
||||
</border>
|
||||
<children>
|
||||
<component id="f5de9" class="javax.swing.JComboBox" binding="mySSHExecutableComboBox" default-binding="true">
|
||||
<component id="26b57" class="javax.swing.JCheckBox" binding="myEnableBranchesWidgetCheckBox" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<selected value="true"/>
|
||||
<text value="Enable &branches widget"/>
|
||||
<toolTipText value="Enables status widget in status bar"/>
|
||||
</properties>
|
||||
</component>
|
||||
<hspacer id="9eafb">
|
||||
<hspacer id="a6134">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</hspacer>
|
||||
</children>
|
||||
</grid>
|
||||
<component id="a6d8e" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<labelFor value="7a626"/>
|
||||
<text resource-bundle="git4idea/i18n/GitBundle" key="git.vcs.config.convert.crlf"/>
|
||||
</properties>
|
||||
</component>
|
||||
<grid id="a4472" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="e7668" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<border type="etched" title="File Conversion"/>
|
||||
<children>
|
||||
<component id="a6d8e" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<labelFor value="7a626"/>
|
||||
<text resource-bundle="git4idea/i18n/GitBundle" key="git.vcs.config.convert.crlf"/>
|
||||
</properties>
|
||||
</component>
|
||||
<hspacer id="9e883">
|
||||
<constraints>
|
||||
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</hspacer>
|
||||
<vspacer id="8bedb">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<component id="7a626" class="javax.swing.JComboBox" binding="myConvertTextFilesComboBox" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<toolTipText resource-bundle="git4idea/i18n/GitBundle" key="git.vcs.config.convert.tooltip"/>
|
||||
</properties>
|
||||
</component>
|
||||
<hspacer id="3c6b8">
|
||||
<component id="a8818" class="javax.swing.JCheckBox" binding="myAskBeforeConversionsCheckBox" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
<grid row="1" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</hspacer>
|
||||
<properties>
|
||||
<selected value="true"/>
|
||||
<text resource-bundle="git4idea/i18n/GitBundle" key="git.vcs.config.convert.ask"/>
|
||||
<toolTipText resource-bundle="git4idea/i18n/GitBundle" key="git.vcs.config.convert.ask.tooltip"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<component id="a8818" class="javax.swing.JCheckBox" binding="myAskBeforeConversionsCheckBox" default-binding="true">
|
||||
<grid id="c9e6b" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="4" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<selected value="true"/>
|
||||
<text resource-bundle="git4idea/i18n/GitBundle" key="git.vcs.config.convert.ask"/>
|
||||
<toolTipText resource-bundle="git4idea/i18n/GitBundle" key="git.vcs.config.convert.ask.tooltip"/>
|
||||
</properties>
|
||||
</component>
|
||||
<properties/>
|
||||
<border type="etched" title="Git"/>
|
||||
<children>
|
||||
<component id="b1a9d" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="git4idea/i18n/GitBundle" key="git.vcs.config.path.label"/>
|
||||
<verifyInputWhenFocusTarget value="false"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="25af7" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myGitField">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<component id="563b2" class="javax.swing.JButton" binding="myTestButton">
|
||||
<constraints>
|
||||
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="2" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<horizontalAlignment value="0"/>
|
||||
<label resource-bundle="git4idea/i18n/GitBundle" key="git.vcs.config.test.label"/>
|
||||
<text resource-bundle="git4idea/i18n/GitBundle" key="git.vcs.config.test"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="5a909" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<labelFor value="f5de9"/>
|
||||
<text resource-bundle="git4idea/i18n/GitBundle" key="git.vcs.config.ssh.mode"/>
|
||||
</properties>
|
||||
</component>
|
||||
<grid id="97c7d" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<hspacer id="9eafb">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</hspacer>
|
||||
<component id="f5de9" class="javax.swing.JComboBox" binding="mySSHExecutableComboBox" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
<vspacer id="4c83d">
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.checkout.branches.GitBranchConfigurations;
|
||||
import git4idea.i18n.GitBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -57,6 +58,10 @@ public class GitVcsPanel {
|
||||
* The confirmation checkbox
|
||||
*/
|
||||
private JCheckBox myAskBeforeConversionsCheckBox;
|
||||
/**
|
||||
* The if selected, the branches widget is enabled in the status bar
|
||||
*/
|
||||
private JCheckBox myEnableBranchesWidgetCheckBox;
|
||||
/**
|
||||
* The project
|
||||
*/
|
||||
@@ -107,6 +112,7 @@ public class GitVcsPanel {
|
||||
myConvertTextFilesComboBox.setSelectedItem(CRLF_CONVERT_TO_PROJECT);
|
||||
myGitField.addBrowseFolderListener(GitBundle.getString("find.git.title"), GitBundle.getString("find.git.description"), project,
|
||||
new FileChooserDescriptor(true, false, false, false, false, false));
|
||||
myEnableBranchesWidgetCheckBox.setSelected(GitBranchConfigurations.getInstance(myProject).isWidgetEnabled());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,6 +154,7 @@ public class GitVcsPanel {
|
||||
mySSHExecutableComboBox.setSelectedItem(settings.isIdeaSsh() ? IDEA_SSH : NATIVE_SSH);
|
||||
myAskBeforeConversionsCheckBox.setSelected(settings.askBeforeLineSeparatorConversion());
|
||||
myConvertTextFilesComboBox.setSelectedItem(crlfPolicyItem(settings));
|
||||
myEnableBranchesWidgetCheckBox.setSelected(GitBranchConfigurations.getInstance(myProject).isWidgetEnabled());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,7 +188,8 @@ public class GitVcsPanel {
|
||||
return !settings.getGitExecutable().equals(myGitField.getText()) ||
|
||||
(settings.isIdeaSsh() != IDEA_SSH.equals(mySSHExecutableComboBox.getSelectedItem())) ||
|
||||
!crlfPolicyItem(settings).equals(myConvertTextFilesComboBox.getSelectedItem()) ||
|
||||
settings.askBeforeLineSeparatorConversion() != myAskBeforeConversionsCheckBox.isSelected();
|
||||
settings.askBeforeLineSeparatorConversion() != myAskBeforeConversionsCheckBox.isSelected() ||
|
||||
GitBranchConfigurations.getInstance(myProject).isWidgetEnabled() != myEnableBranchesWidgetCheckBox.isSelected();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,5 +213,6 @@ public class GitVcsPanel {
|
||||
}
|
||||
settings.setLineSeparatorsConversion(conversionPolicy);
|
||||
settings.setAskBeforeLineSeparatorConversion(myAskBeforeConversionsCheckBox.isSelected());
|
||||
GitBranchConfigurations.getInstance(myProject).setWidgetEnabled(myEnableBranchesWidgetCheckBox.isSelected());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ public class HgChangesetStatus extends JLabel implements CustomStatusBarWidget {
|
||||
return "HgChangeSetStatus";
|
||||
}
|
||||
|
||||
public WidgetPresentation getPresentation(@NotNull Type type) {
|
||||
public WidgetPresentation getPresentation(@NotNull PlatformType type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user