mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
/* The following code was generated by JFlex 1.4.3 on 10/28/14 3:07 PM */
|
||||
/* The following code was generated by JFlex 1.4.3 on 10/28/14 5:18 PM */
|
||||
|
||||
/* It's an automatically generated code. Do not modify it. */
|
||||
package org.intellij.lang.regexp;
|
||||
@@ -15,7 +15,7 @@ import java.util.EnumSet;
|
||||
/**
|
||||
* This class is a scanner generated by
|
||||
* <a href="http://www.jflex.de/">JFlex</a> 1.4.3
|
||||
* on 10/28/14 3:07 PM from the specification file
|
||||
* on 10/28/14 5:18 PM from the specification file
|
||||
* <tt>/Users/bas/Projects/IntelliJ IDEA Ultimate/tools/lexer/../../community/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex</tt>
|
||||
*/
|
||||
class _RegExLexer implements FlexLexer {
|
||||
@@ -24,7 +24,7 @@ class _RegExLexer implements FlexLexer {
|
||||
|
||||
/** lexical states */
|
||||
public static final int EMBRACED = 4;
|
||||
public static final int CLASS1PY = 8;
|
||||
public static final int NEGATE_CLASS1 = 8;
|
||||
public static final int PY_NAMED_GROUP_REF = 22;
|
||||
public static final int QUOTED = 2;
|
||||
public static final int OPTIONS = 14;
|
||||
@@ -730,68 +730,68 @@ class _RegExLexer implements FlexLexer {
|
||||
{ yybegin(YYINITIAL); return RegExpTT.GROUP_END;
|
||||
}
|
||||
case 88: break;
|
||||
case 37:
|
||||
{ yybegin(YYINITIAL); return RegExpTT.COLON;
|
||||
}
|
||||
case 89: break;
|
||||
case 6:
|
||||
{ return RegExpTT.GROUP_END;
|
||||
}
|
||||
case 90: break;
|
||||
case 25:
|
||||
{ assert false : yytext();
|
||||
}
|
||||
case 91: break;
|
||||
case 18:
|
||||
{ return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CHARACTER;
|
||||
}
|
||||
case 92: break;
|
||||
case 46:
|
||||
{ return commentMode ? RegExpTT.CHARACTER : RegExpTT.REDUNDANT_ESCAPE;
|
||||
}
|
||||
case 93: break;
|
||||
case 23:
|
||||
{ return RegExpTT.NAME;
|
||||
}
|
||||
case 94: break;
|
||||
case 29:
|
||||
{ yypopstate(); return RegExpTT.CLASS_END;
|
||||
}
|
||||
case 95: break;
|
||||
case 34:
|
||||
{ yybegin(YYINITIAL); return RegExpTT.BAD_CHARACTER;
|
||||
}
|
||||
case 96: break;
|
||||
case 52:
|
||||
{ yypushstate(QUOTED); return RegExpTT.QUOTE_BEGIN;
|
||||
}
|
||||
case 97: break;
|
||||
case 21:
|
||||
{ return RegExpTT.NUMBER;
|
||||
}
|
||||
case 98: break;
|
||||
case 4:
|
||||
{ return RegExpTT.DOT;
|
||||
}
|
||||
case 99: break;
|
||||
case 72:
|
||||
{ return RegExpTT.NEG_LOOKBEHIND;
|
||||
}
|
||||
case 100: break;
|
||||
case 33:
|
||||
{ yypopstate(); if (allowCategoryShorthand) return RegExpTT.CATEGORY_SHORT_HAND; else yypushback(1);
|
||||
}
|
||||
case 101: break;
|
||||
case 44:
|
||||
{ return (allowOctalNoLeadingZero ? RegExpTT.OCT_CHAR : RegExpTT.BAD_OCT_VALUE);
|
||||
}
|
||||
case 102: break;
|
||||
case 41:
|
||||
// lookahead expression with fixed base length
|
||||
zzMarkedPos = zzStartRead + 1;
|
||||
{ yypushstate(CLASS1);
|
||||
{ if (allowEmptyCharacterClass) yypushstate(CLASS2); else yypushstate(CLASS1);
|
||||
return RegExpTT.CLASS_BEGIN;
|
||||
}
|
||||
case 89: break;
|
||||
case 37:
|
||||
{ yybegin(YYINITIAL); return RegExpTT.COLON;
|
||||
}
|
||||
case 90: break;
|
||||
case 6:
|
||||
{ return RegExpTT.GROUP_END;
|
||||
}
|
||||
case 91: break;
|
||||
case 25:
|
||||
{ assert false : yytext();
|
||||
}
|
||||
case 92: break;
|
||||
case 18:
|
||||
{ return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CHARACTER;
|
||||
}
|
||||
case 93: break;
|
||||
case 46:
|
||||
{ return commentMode ? RegExpTT.CHARACTER : RegExpTT.REDUNDANT_ESCAPE;
|
||||
}
|
||||
case 94: break;
|
||||
case 23:
|
||||
{ return RegExpTT.NAME;
|
||||
}
|
||||
case 95: break;
|
||||
case 29:
|
||||
{ yypopstate(); return RegExpTT.CLASS_END;
|
||||
}
|
||||
case 96: break;
|
||||
case 34:
|
||||
{ yybegin(YYINITIAL); return RegExpTT.BAD_CHARACTER;
|
||||
}
|
||||
case 97: break;
|
||||
case 52:
|
||||
{ yypushstate(QUOTED); return RegExpTT.QUOTE_BEGIN;
|
||||
}
|
||||
case 98: break;
|
||||
case 21:
|
||||
{ return RegExpTT.NUMBER;
|
||||
}
|
||||
case 99: break;
|
||||
case 4:
|
||||
{ return RegExpTT.DOT;
|
||||
}
|
||||
case 100: break;
|
||||
case 72:
|
||||
{ return RegExpTT.NEG_LOOKBEHIND;
|
||||
}
|
||||
case 101: break;
|
||||
case 33:
|
||||
{ yypopstate(); if (allowCategoryShorthand) return RegExpTT.CATEGORY_SHORT_HAND; else yypushback(1);
|
||||
}
|
||||
case 102: break;
|
||||
case 44:
|
||||
{ return (allowOctalNoLeadingZero ? RegExpTT.OCT_CHAR : RegExpTT.BAD_OCT_VALUE);
|
||||
}
|
||||
case 103: break;
|
||||
case 63:
|
||||
{ return RegExpTT.NEG_LOOKAHEAD;
|
||||
@@ -809,18 +809,6 @@ class _RegExLexer implements FlexLexer {
|
||||
{ yybegin(QUOTED_NAMED_GROUP); return RegExpTT.RUBY_QUOTED_NAMED_GROUP;
|
||||
}
|
||||
case 107: break;
|
||||
case 66:
|
||||
// lookahead expression with fixed base length
|
||||
zzMarkedPos = zzStartRead + 1;
|
||||
{ if (allowEmptyCharacterClass) {
|
||||
yypushstate(CLASS1PY);
|
||||
}
|
||||
else {
|
||||
yypushstate(CLASS2);
|
||||
}
|
||||
return RegExpTT.CLASS_BEGIN;
|
||||
}
|
||||
case 108: break;
|
||||
case 28:
|
||||
{ if (allowNestedCharacterClasses) {
|
||||
yypushstate(CLASS2);
|
||||
@@ -828,24 +816,24 @@ class _RegExLexer implements FlexLexer {
|
||||
}
|
||||
return RegExpTT.CHARACTER;
|
||||
}
|
||||
case 109: break;
|
||||
case 108: break;
|
||||
case 19:
|
||||
{ if (commentMode) { yypushstate(COMMENT); return RegExpTT.COMMENT; } else return RegExpTT.CHARACTER;
|
||||
}
|
||||
case 110: break;
|
||||
case 109: break;
|
||||
case 51:
|
||||
{ yypushstate(PROP); return RegExpTT.PROPERTY;
|
||||
}
|
||||
case 111: break;
|
||||
case 110: break;
|
||||
case 8:
|
||||
{ yypushstate(CLASS2);
|
||||
return RegExpTT.CLASS_BEGIN;
|
||||
}
|
||||
case 112: break;
|
||||
case 111: break;
|
||||
case 71:
|
||||
{ return RegExpTT.POS_LOOKBEHIND;
|
||||
}
|
||||
case 113: break;
|
||||
case 112: break;
|
||||
case 20:
|
||||
{ if (allowDanglingMetacharacters) {
|
||||
yypopstate(); yypushback(1);
|
||||
@@ -853,15 +841,15 @@ class _RegExLexer implements FlexLexer {
|
||||
return RegExpTT.BAD_CHARACTER;
|
||||
}
|
||||
}
|
||||
case 114: break;
|
||||
case 113: break;
|
||||
case 73:
|
||||
{ return RegExpTT.HEX_CHAR;
|
||||
}
|
||||
case 115: break;
|
||||
case 114: break;
|
||||
case 1:
|
||||
{ handleOptions(); return RegExpTT.OPTIONS_ON;
|
||||
}
|
||||
case 116: break;
|
||||
case 115: break;
|
||||
case 43:
|
||||
{ if (yystate() == CLASS2) return RegExpTT.ESC_CHARACTER;
|
||||
while (yylength() > 2 && Integer.parseInt(yytext().toString().substring(1)) > capturingGroupCount) {
|
||||
@@ -869,55 +857,55 @@ class _RegExLexer implements FlexLexer {
|
||||
}
|
||||
return RegExpTT.BACKREF;
|
||||
}
|
||||
case 117: break;
|
||||
case 116: break;
|
||||
case 59:
|
||||
{ return allowNestedCharacterClasses ? RegExpTT.ANDAND : RegExpTT.CHARACTER;
|
||||
}
|
||||
case 118: break;
|
||||
case 117: break;
|
||||
case 2:
|
||||
{ yypopstate(); return RegExpTT.COMMENT;
|
||||
}
|
||||
case 119: break;
|
||||
case 118: break;
|
||||
case 17:
|
||||
{ return RegExpTT.MINUS;
|
||||
}
|
||||
case 120: break;
|
||||
case 119: break;
|
||||
case 47:
|
||||
{ return RegExpTT.ESC_CTRL_CHARACTER;
|
||||
}
|
||||
case 121: break;
|
||||
case 120: break;
|
||||
case 32:
|
||||
{ yypopstate(); yypushstate(EMBRACED); return RegExpTT.LBRACE;
|
||||
}
|
||||
case 122: break;
|
||||
case 121: break;
|
||||
case 13:
|
||||
{ return RegExpTT.QUEST;
|
||||
}
|
||||
case 123: break;
|
||||
case 122: break;
|
||||
case 5:
|
||||
{ capturingGroupCount++; return RegExpTT.GROUP_BEGIN;
|
||||
}
|
||||
case 124: break;
|
||||
case 123: break;
|
||||
case 15:
|
||||
{ return RegExpTT.PLUS;
|
||||
}
|
||||
case 125: break;
|
||||
case 124: break;
|
||||
case 67:
|
||||
{ return RegExpTT.OCT_CHAR;
|
||||
}
|
||||
case 126: break;
|
||||
case 125: break;
|
||||
case 39:
|
||||
{ yybegin(YYINITIAL); return RegExpTT.QUOTE;
|
||||
}
|
||||
case 127: break;
|
||||
case 126: break;
|
||||
case 31:
|
||||
{ yypopstate(); yypushback(1);
|
||||
}
|
||||
case 128: break;
|
||||
case 127: break;
|
||||
case 27:
|
||||
{ yybegin(CLASS1); return RegExpTT.CARET;
|
||||
}
|
||||
case 129: break;
|
||||
case 128: break;
|
||||
case 57:
|
||||
// lookahead expression with fixed base length
|
||||
zzMarkedPos = zzStartRead + 1;
|
||||
@@ -927,71 +915,78 @@ class _RegExLexer implements FlexLexer {
|
||||
}
|
||||
return RegExpTT.CHARACTER;
|
||||
}
|
||||
case 130: break;
|
||||
case 129: break;
|
||||
case 58:
|
||||
{ if (!allowNestedCharacterClasses) return RegExpTT.CHARACTER;
|
||||
return RegExpTT.REDUNDANT_ESCAPE;
|
||||
}
|
||||
case 131: break;
|
||||
case 130: break;
|
||||
case 38:
|
||||
{ yybegin(YYINITIAL); return RegExpTT.GT;
|
||||
}
|
||||
case 132: break;
|
||||
case 131: break;
|
||||
case 69:
|
||||
{ yybegin(PY_NAMED_GROUP_REF); return RegExpTT.PYTHON_NAMED_GROUP_REF;
|
||||
}
|
||||
case 133: break;
|
||||
case 132: break;
|
||||
case 16:
|
||||
{ return RegExpTT.UNION;
|
||||
}
|
||||
case 134: break;
|
||||
case 133: break;
|
||||
case 3:
|
||||
{ return RegExpTT.CHARACTER;
|
||||
}
|
||||
case 135: break;
|
||||
case 134: break;
|
||||
case 64:
|
||||
{ yybegin(NAMED_GROUP); return RegExpTT.RUBY_NAMED_GROUP;
|
||||
}
|
||||
case 136: break;
|
||||
case 135: break;
|
||||
case 40:
|
||||
{ yybegin(OPTIONS); return RegExpTT.SET_OPTIONS;
|
||||
}
|
||||
case 137: break;
|
||||
case 136: break;
|
||||
case 26:
|
||||
{ yybegin(CLASS2); return RegExpTT.CHARACTER;
|
||||
}
|
||||
case 138: break;
|
||||
case 137: break;
|
||||
case 68:
|
||||
{ if (xmlSchemaMode) { yypushback(1); return RegExpTT.CHAR_CLASS; } else return RegExpTT.CTRL;
|
||||
}
|
||||
case 139: break;
|
||||
case 138: break;
|
||||
case 30:
|
||||
{ return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.ESC_CHARACTER;
|
||||
}
|
||||
case 140: break;
|
||||
case 139: break;
|
||||
case 12:
|
||||
{ return RegExpTT.DOLLAR;
|
||||
}
|
||||
case 141: break;
|
||||
case 140: break;
|
||||
case 50:
|
||||
{ if (xmlSchemaMode) return RegExpTT.CHAR_CLASS; else return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN;
|
||||
}
|
||||
case 142: break;
|
||||
case 141: break;
|
||||
case 42:
|
||||
{ return RegExpTT.REDUNDANT_ESCAPE;
|
||||
}
|
||||
case 143: break;
|
||||
case 142: break;
|
||||
case 55:
|
||||
{ return (allowHexDigitClass || allowHorizontalWhitespaceClass ? RegExpTT.CHAR_CLASS : StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN);
|
||||
}
|
||||
case 144: break;
|
||||
case 143: break;
|
||||
case 48:
|
||||
{ return yystate() != CLASS2 ? RegExpTT.BOUNDARY : RegExpTT.ESC_CHARACTER;
|
||||
}
|
||||
case 145: break;
|
||||
case 144: break;
|
||||
case 22:
|
||||
{ yypopstate(); return RegExpTT.RBRACE;
|
||||
}
|
||||
case 145: break;
|
||||
case 66:
|
||||
// lookahead expression with fixed base length
|
||||
zzMarkedPos = zzStartRead + 1;
|
||||
{ if (allowEmptyCharacterClass) yypushstate(CLASS2); else yypushstate(NEGATE_CLASS1);
|
||||
return RegExpTT.CLASS_BEGIN;
|
||||
}
|
||||
case 146: break;
|
||||
case 54:
|
||||
{ return StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN;
|
||||
|
||||
@@ -75,7 +75,7 @@ import java.util.EnumSet;
|
||||
%xstate QUOTED
|
||||
%xstate EMBRACED
|
||||
%xstate CLASS1
|
||||
%xstate CLASS1PY
|
||||
%xstate NEGATE_CLASS1
|
||||
%state CLASS2
|
||||
%state PROP
|
||||
%xstate OPTIONS
|
||||
@@ -228,18 +228,11 @@ HEX_CHAR=[0-9a-fA-F]
|
||||
}
|
||||
}
|
||||
|
||||
{LBRACKET} / {RBRACKET} { yypushstate(CLASS1);
|
||||
{LBRACKET} / {RBRACKET} { if (allowEmptyCharacterClass) yypushstate(CLASS2); else yypushstate(CLASS1);
|
||||
return RegExpTT.CLASS_BEGIN; }
|
||||
|
||||
/* Python understands that, Java doesn't */
|
||||
{LBRACKET} / "^" {RBRACKET} { if (allowEmptyCharacterClass) {
|
||||
yypushstate(CLASS1PY);
|
||||
}
|
||||
else {
|
||||
yypushstate(CLASS2);
|
||||
}
|
||||
return RegExpTT.CLASS_BEGIN;
|
||||
}
|
||||
{LBRACKET} / "^" {RBRACKET} { if (allowEmptyCharacterClass) yypushstate(CLASS2); else yypushstate(NEGATE_CLASS1);
|
||||
return RegExpTT.CLASS_BEGIN; }
|
||||
|
||||
{LBRACKET} { yypushstate(CLASS2);
|
||||
return RegExpTT.CLASS_BEGIN; }
|
||||
@@ -250,7 +243,7 @@ HEX_CHAR=[0-9a-fA-F]
|
||||
. { assert false : yytext(); }
|
||||
}
|
||||
|
||||
<CLASS1PY> {
|
||||
<NEGATE_CLASS1> {
|
||||
"^" { yybegin(CLASS1); return RegExpTT.CARET; }
|
||||
. { assert false : yytext(); }
|
||||
}
|
||||
|
||||
@@ -296,6 +296,10 @@
|
||||
<pattern>a[]b</pattern>
|
||||
<expected>ERR</expected>
|
||||
</test>
|
||||
<test>
|
||||
<pattern>[^]</pattern>
|
||||
<expected>ERR</expected>
|
||||
</test>
|
||||
<test>
|
||||
<pattern>[abhgefdc]ij</pattern>
|
||||
<expected>OK</expected>
|
||||
@@ -583,11 +587,11 @@
|
||||
<pattern>\x4a</pattern>
|
||||
<expected>OK</expected>
|
||||
</test>
|
||||
<test>
|
||||
<test verify="false">
|
||||
<pattern>\x{0}</pattern>
|
||||
<expected>OK</expected>
|
||||
</test>
|
||||
<test>
|
||||
<test verify="false">
|
||||
<pattern>\x{2011F}</pattern>
|
||||
<expected>OK</expected>
|
||||
</test>
|
||||
@@ -1043,7 +1047,7 @@
|
||||
</bug>
|
||||
|
||||
<bug id="IDEA-131542">
|
||||
<test>
|
||||
<test verify="false">
|
||||
<pattern>\h \H \v \V</pattern>
|
||||
<expected>OK</expected>
|
||||
</test>
|
||||
|
||||
@@ -104,7 +104,7 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
|
||||
@Nullable
|
||||
private String myBytecodeTargetLevel = null; // null means compiler default
|
||||
private final Map<String, String> myModuleBytecodeTarget = new java.util.HashMap<String, String>();
|
||||
private final Map<String, String> myModuleBytecodeTarget = new HashMap<String, String>();
|
||||
|
||||
public CompilerConfigurationImpl(Project project) {
|
||||
myProject = project;
|
||||
@@ -112,28 +112,78 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
Disposer.register(project, myExcludedEntriesConfiguration);
|
||||
MessageBusConnection connection = project.getMessageBus().connect(project);
|
||||
connection.subscribe(ProjectTopics.MODULES, new ModuleAdapter() {
|
||||
@Override
|
||||
public void beforeModuleRemoved(Project project, Module module) {
|
||||
getAnnotationProcessingConfiguration(module).removeModuleName(module.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moduleAdded(Project project, Module module) {
|
||||
myProcessorsProfilesMap = null; // clear cache
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Element getState() {
|
||||
Element state = new Element("state");
|
||||
try {
|
||||
@NonNls final Element e = new Element("state");
|
||||
writeExternal(e);
|
||||
return e;
|
||||
DefaultJDOMExternalizer.writeExternal(this, state);
|
||||
}
|
||||
catch (WriteExternalException e1) {
|
||||
LOG.error(e1);
|
||||
catch (WriteExternalException e) {
|
||||
LOG.error(e);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!myAddNotNullAssertions) {
|
||||
addChild(state, JpsJavaCompilerConfigurationSerializer.ADD_NOTNULL_ASSERTIONS).setAttribute(
|
||||
JpsJavaCompilerConfigurationSerializer.ENABLED, String.valueOf(myAddNotNullAssertions));
|
||||
}
|
||||
|
||||
if (myExcludedEntriesConfiguration.getExcludeEntryDescriptions().length > 0) {
|
||||
myExcludedEntriesConfiguration.writeExternal(addChild(state, JpsJavaCompilerConfigurationSerializer.EXCLUDE_FROM_COMPILE));
|
||||
}
|
||||
|
||||
final Element newChild = addChild(state, JpsJavaCompilerConfigurationSerializer.RESOURCE_EXTENSIONS);
|
||||
for (final String pattern : getRegexpPatterns()) {
|
||||
addChild(newChild, JpsJavaCompilerConfigurationSerializer.ENTRY).setAttribute(JpsJavaCompilerConfigurationSerializer.NAME, pattern);
|
||||
}
|
||||
|
||||
if (myWildcardPatternsInitialized || !myWildcardPatterns.isEmpty()) {
|
||||
final Element wildcardPatterns = addChild(state, JpsJavaCompilerConfigurationSerializer.WILDCARD_RESOURCE_PATTERNS);
|
||||
for (final String wildcardPattern : myWildcardPatterns) {
|
||||
addChild(wildcardPatterns, JpsJavaCompilerConfigurationSerializer.ENTRY).setAttribute(JpsJavaCompilerConfigurationSerializer.NAME, wildcardPattern);
|
||||
}
|
||||
}
|
||||
|
||||
final Element annotationProcessingSettings = addChild(state, JpsJavaCompilerConfigurationSerializer.ANNOTATION_PROCESSING);
|
||||
final Element defaultProfileElem = addChild(annotationProcessingSettings, "profile").setAttribute("default", "true");
|
||||
AnnotationProcessorProfileSerializer.writeExternal(myDefaultProcessorsProfile, defaultProfileElem);
|
||||
for (ProcessorConfigProfile profile : myModuleProcessorProfiles) {
|
||||
final Element profileElem = addChild(annotationProcessingSettings, "profile").setAttribute("default", "false");
|
||||
AnnotationProcessorProfileSerializer.writeExternal(profile, profileElem);
|
||||
}
|
||||
|
||||
if (!StringUtil.isEmpty(myBytecodeTargetLevel) || !myModuleBytecodeTarget.isEmpty()) {
|
||||
final Element bytecodeTarget = addChild(state, JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL);
|
||||
if (!StringUtil.isEmpty(myBytecodeTargetLevel)) {
|
||||
bytecodeTarget.setAttribute(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE, myBytecodeTargetLevel);
|
||||
}
|
||||
if (!myModuleBytecodeTarget.isEmpty()) {
|
||||
final List<String> moduleNames = new ArrayList<String>(myModuleBytecodeTarget.keySet());
|
||||
Collections.sort(moduleNames, String.CASE_INSENSITIVE_ORDER);
|
||||
for (String name : moduleNames) {
|
||||
final Element moduleElement = addChild(bytecodeTarget, JpsJavaCompilerConfigurationSerializer.MODULE);
|
||||
moduleElement.setAttribute(JpsJavaCompilerConfigurationSerializer.NAME, name);
|
||||
final String value = myModuleBytecodeTarget.get(name);
|
||||
moduleElement.setAttribute(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE, value != null ? value : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(Element state) {
|
||||
try {
|
||||
readExternal(state);
|
||||
@@ -162,6 +212,7 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
return myModuleBytecodeTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBytecodeTargetLevel(Module module, String level) {
|
||||
final String previous;
|
||||
if (StringUtil.isEmpty(level)) {
|
||||
@@ -229,11 +280,14 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disposeComponent() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initComponent() { }
|
||||
|
||||
@Override
|
||||
public void projectClosed() {
|
||||
}
|
||||
|
||||
@@ -242,6 +296,7 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
return JAVAC_EXTERNAL_BACKEND;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void projectOpened() {
|
||||
createCompilers();
|
||||
}
|
||||
@@ -304,6 +359,7 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
return ArrayUtil.toStringArray(myWildcardPatterns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceFilePattern(String namePattern) throws MalformedPatternException {
|
||||
addWildcardResourcePattern(namePattern);
|
||||
}
|
||||
@@ -321,6 +377,7 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
return myExcludedEntriesConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExcludedFromCompilation(final VirtualFile virtualFile) {
|
||||
return myExcludedEntriesConfiguration.isExcluded(virtualFile);
|
||||
}
|
||||
@@ -505,6 +562,7 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
return wildcardPattern.length() > 1 && wildcardPattern.charAt(0) == '!';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResourceFile(String name) {
|
||||
return isResourceFile(name, null);
|
||||
}
|
||||
@@ -647,7 +705,7 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
final Element bytecodeTargetElement = parentNode.getChild(JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL);
|
||||
if (bytecodeTargetElement != null) {
|
||||
myBytecodeTargetLevel = bytecodeTargetElement.getAttributeValue(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE);
|
||||
for (Element elem : (Collection<Element>)bytecodeTargetElement.getChildren(JpsJavaCompilerConfigurationSerializer.MODULE)) {
|
||||
for (Element elem : bytecodeTargetElement.getChildren(JpsJavaCompilerConfigurationSerializer.MODULE)) {
|
||||
final String name = elem.getAttributeValue(JpsJavaCompilerConfigurationSerializer.NAME);
|
||||
if (name == null) {
|
||||
continue;
|
||||
@@ -746,56 +804,7 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
}
|
||||
}
|
||||
|
||||
private void writeExternal(Element parentNode) throws WriteExternalException {
|
||||
DefaultJDOMExternalizer.writeExternal(this, parentNode);
|
||||
|
||||
if (myAddNotNullAssertions != true) {
|
||||
addChild(parentNode, JpsJavaCompilerConfigurationSerializer.ADD_NOTNULL_ASSERTIONS).setAttribute(
|
||||
JpsJavaCompilerConfigurationSerializer.ENABLED, String.valueOf(myAddNotNullAssertions));
|
||||
}
|
||||
|
||||
if(myExcludedEntriesConfiguration.getExcludeEntryDescriptions().length > 0) {
|
||||
myExcludedEntriesConfiguration.writeExternal(addChild(parentNode, JpsJavaCompilerConfigurationSerializer.EXCLUDE_FROM_COMPILE));
|
||||
}
|
||||
|
||||
final Element newChild = addChild(parentNode, JpsJavaCompilerConfigurationSerializer.RESOURCE_EXTENSIONS);
|
||||
for (final String pattern : getRegexpPatterns()) {
|
||||
addChild(newChild, JpsJavaCompilerConfigurationSerializer.ENTRY).setAttribute(JpsJavaCompilerConfigurationSerializer.NAME, pattern);
|
||||
}
|
||||
|
||||
if (myWildcardPatternsInitialized || !myWildcardPatterns.isEmpty()) {
|
||||
final Element wildcardPatterns = addChild(parentNode, JpsJavaCompilerConfigurationSerializer.WILDCARD_RESOURCE_PATTERNS);
|
||||
for (final String wildcardPattern : myWildcardPatterns) {
|
||||
addChild(wildcardPatterns, JpsJavaCompilerConfigurationSerializer.ENTRY).setAttribute(JpsJavaCompilerConfigurationSerializer.NAME, wildcardPattern);
|
||||
}
|
||||
}
|
||||
|
||||
final Element annotationProcessingSettings = addChild(parentNode, JpsJavaCompilerConfigurationSerializer.ANNOTATION_PROCESSING);
|
||||
final Element defaultProfileElem = addChild(annotationProcessingSettings, "profile").setAttribute("default", "true");
|
||||
AnnotationProcessorProfileSerializer.writeExternal(myDefaultProcessorsProfile, defaultProfileElem);
|
||||
for (ProcessorConfigProfile profile : myModuleProcessorProfiles) {
|
||||
final Element profileElem = addChild(annotationProcessingSettings, "profile").setAttribute("default", "false");
|
||||
AnnotationProcessorProfileSerializer.writeExternal(profile, profileElem);
|
||||
}
|
||||
|
||||
if (!StringUtil.isEmpty(myBytecodeTargetLevel) || !myModuleBytecodeTarget.isEmpty()) {
|
||||
final Element bytecodeTarget = addChild(parentNode, JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL);
|
||||
if (!StringUtil.isEmpty(myBytecodeTargetLevel)) {
|
||||
bytecodeTarget.setAttribute(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE, myBytecodeTargetLevel);
|
||||
}
|
||||
if (!myModuleBytecodeTarget.isEmpty()) {
|
||||
final List<String> moduleNames = new ArrayList<String>(myModuleBytecodeTarget.keySet());
|
||||
Collections.sort(moduleNames, String.CASE_INSENSITIVE_ORDER);
|
||||
for (String name : moduleNames) {
|
||||
final Element moduleElement = addChild(bytecodeTarget, JpsJavaCompilerConfigurationSerializer.MODULE);
|
||||
moduleElement.setAttribute(JpsJavaCompilerConfigurationSerializer.NAME, name);
|
||||
final String value = myModuleBytecodeTarget.get(name);
|
||||
moduleElement.setAttribute(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE, value != null? value : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull @NonNls
|
||||
public String getComponentName() {
|
||||
return "CompilerConfiguration";
|
||||
@@ -839,9 +848,11 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
);
|
||||
final String wildcardPatterns = Messages.showInputDialog(
|
||||
myProject, message, CompilerBundle.message("pattern.conversion.dialog.title"), Messages.getWarningIcon(), initialPatternString, new InputValidator() {
|
||||
@Override
|
||||
public boolean checkInput(String inputString) {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean canClose(String inputString) {
|
||||
final StringTokenizer tokenizer = new StringTokenizer(inputString, ";", false);
|
||||
StringBuilder malformedPatterns = new StringBuilder();
|
||||
@@ -925,6 +936,7 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
return extensionsString.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompilableResourceFile(final Project project, final VirtualFile file) {
|
||||
if (!isResourceFile(file)) {
|
||||
return false;
|
||||
@@ -938,7 +950,7 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
@Nullable final Pattern dir;
|
||||
@Nullable final Pattern srcRoot;
|
||||
|
||||
private CompiledPattern(Pattern fileName, Pattern dir, Pattern srcRoot) {
|
||||
private CompiledPattern(@NotNull Pattern fileName, @Nullable Pattern dir, @Nullable Pattern srcRoot) {
|
||||
this.fileName = fileName;
|
||||
this.dir = dir;
|
||||
this.srcRoot = srcRoot;
|
||||
|
||||
@@ -32,7 +32,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
||||
@@ -176,7 +175,7 @@ public class JavaExecutionStack extends XExecutionStack {
|
||||
}
|
||||
if (first || DebuggerSettings.getInstance().SHOW_LIBRARY_STACKFRAMES || (!frame.getDescriptor().isSynthetic() && !frame.getDescriptor().isInLibraryContent())) {
|
||||
if (++myAdded > mySkip) {
|
||||
myContainer.addStackFrames(Arrays.asList(frame), false);
|
||||
myContainer.addStackFrames(Collections.singletonList(frame), false);
|
||||
}
|
||||
}
|
||||
myDebugProcess.getManagerThread().schedule(
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -88,7 +88,7 @@ class ImageObjectRenderer extends CompoundReferenceRenderer implements FullValue
|
||||
if (cls != null) {
|
||||
List<Method> methods = cls.methodsByName(methodName);
|
||||
if (!methods.isEmpty()) {
|
||||
return process.invokeMethod(evaluationContext, cls, methods.get(0), Arrays.asList(obj));
|
||||
return process.invokeMethod(evaluationContext, cls, methods.get(0), Collections.singletonList(obj));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -50,10 +50,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes;
|
||||
import javax.tools.*;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author egor
|
||||
@@ -250,9 +247,9 @@ public class CompilingEvaluator implements ExpressionEvaluator {
|
||||
StringReference url = proxy.mirrorOf("file:a");
|
||||
keep(url, context);
|
||||
ObjectReference reference = classType.newInstance(threadReference, classType.concreteMethodByName("<init>", "(Ljava/lang/String;)V"),
|
||||
Arrays.asList(url), ClassType.INVOKE_SINGLE_THREADED);
|
||||
Collections.singletonList(url), ClassType.INVOKE_SINGLE_THREADED);
|
||||
keep(reference, context);
|
||||
arrayRef.setValues(Arrays.asList(reference));
|
||||
arrayRef.setValues(Collections.singletonList(reference));
|
||||
return arrayRef;
|
||||
}
|
||||
|
||||
@@ -290,7 +287,7 @@ public class CompilingEvaluator implements ExpressionEvaluator {
|
||||
diagnostic,
|
||||
options,
|
||||
null,
|
||||
Arrays.asList(new SourceFileObject(getMainClassName(), JavaFileObject.Kind.SOURCE, getClassCode()))
|
||||
Collections.singletonList(new SourceFileObject(getMainClassName(), JavaFileObject.Kind.SOURCE, getClassCode()))
|
||||
).call()) {
|
||||
StringBuilder res = new StringBuilder("Compilation failed:\n");
|
||||
for (Diagnostic<? extends JavaFileObject> d : diagnostic.getDiagnostics()) {
|
||||
|
||||
@@ -19,9 +19,7 @@ import com.sun.jdi.Method;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
@@ -29,7 +27,7 @@ import java.util.Set;
|
||||
*/
|
||||
public class MethodsTracker {
|
||||
private final Map<Method, Integer> myMethodToOccurrenceMap = new HashMap<Method, Integer>();
|
||||
private final Set<Integer> myProcessedFrames = new HashSet<Integer>();
|
||||
private final Map<Integer, Integer> myInitialOccurence = new HashMap<Integer, Integer>();
|
||||
|
||||
public final class MethodOccurrence {
|
||||
private final Method myMethod;
|
||||
@@ -54,12 +52,13 @@ public class MethodsTracker {
|
||||
}
|
||||
|
||||
public MethodOccurrence getMethodOccurrence(int frameIndex, @Nullable Method method) {
|
||||
int occurenceIndex = getOccurrenceCount(method);
|
||||
if (!myProcessedFrames.contains(frameIndex)) {
|
||||
myMethodToOccurrenceMap.put(method, occurenceIndex + 1);
|
||||
myProcessedFrames.add(frameIndex);
|
||||
Integer initial = myInitialOccurence.get(frameIndex);
|
||||
if (initial == null) {
|
||||
initial = getOccurrenceCount(method);
|
||||
myMethodToOccurrenceMap.put(method, initial + 1);
|
||||
myInitialOccurence.put(frameIndex, initial);
|
||||
}
|
||||
return new MethodOccurrence(method, occurenceIndex);
|
||||
return new MethodOccurrence(method, initial);
|
||||
}
|
||||
|
||||
private int getOccurrenceCount(Method method) {
|
||||
|
||||
@@ -26,7 +26,10 @@ import com.intellij.openapi.application.ex.ApplicationUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.progress.*;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.progress.impl.BackgroundableProcessIndicator;
|
||||
import com.intellij.openapi.progress.impl.ProgressManagerImpl;
|
||||
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
|
||||
@@ -105,12 +108,20 @@ public class RefResolveServiceImpl extends RefResolveService implements Runnable
|
||||
myApplication = application;
|
||||
myProjectFileIndex = projectFileIndex;
|
||||
if (ENABLED) {
|
||||
File indexFile = new File(getStorageDirectory(), "index");
|
||||
File dataFile = new File(getStorageDirectory(), "data");
|
||||
fileIsResolved = ConcurrentBitSet.readFrom(new File(getStorageDirectory(), "bitSet"));
|
||||
|
||||
final boolean initial = !indexFile.exists() || !dataFile.exists();
|
||||
storage = new PersistentIntList(indexFile, dataFile, initial);
|
||||
int maxId = FSRecords.getMaxId();
|
||||
PersistentIntList list = new PersistentIntList(dataFile, dataFile.exists() ? 0 : maxId);
|
||||
if (list.getSize() == maxId) {
|
||||
storage = list;
|
||||
}
|
||||
else {
|
||||
// just to be safe, re-resolve all if VFS files count changes since last restart
|
||||
list.dispose();
|
||||
storage = new PersistentIntList(dataFile, maxId);
|
||||
fileIsResolved.clear();
|
||||
}
|
||||
Disposer.register(this, storage);
|
||||
if (!application.isUnitTestMode()) {
|
||||
startupManager.runWhenProjectIsInitialized(new Runnable() {
|
||||
@@ -716,10 +727,8 @@ public class RefResolveServiceImpl extends RefResolveService implements Runnable
|
||||
if (myProject.isDisposed()) throw new ProcessCanceledException();
|
||||
if (fileCount.incrementAndGet() % 100 == 0) {
|
||||
PsiManager.getInstance(myProject).dropResolveCaches();
|
||||
synchronized (storage) {
|
||||
storage.flush();
|
||||
}
|
||||
try {
|
||||
storage.flush();
|
||||
log.flush();
|
||||
}
|
||||
catch (IOException e) {
|
||||
|
||||
@@ -206,6 +206,11 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
|
||||
protected PsiClass getContainingClass(PsiMethod method) {
|
||||
return containingClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean acceptVarargs() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
processor.setArgumentList(argumentList);
|
||||
|
||||
|
||||
@@ -24,3 +24,12 @@ class A<T> {
|
||||
bar(s(get(), ""));
|
||||
}
|
||||
}
|
||||
|
||||
class B<T> {
|
||||
public B(T entity) {}
|
||||
public B(T entity, Integer... error){}
|
||||
|
||||
void foo(final Integer generalError){
|
||||
B value = new B<>("", generalError);
|
||||
}
|
||||
}
|
||||
@@ -21,4 +21,22 @@ import com.intellij.xml.XmlElementDescriptor;
|
||||
* @author Maxim.Mossienko
|
||||
*/
|
||||
public interface JspElementDescriptor extends XmlElementDescriptor {
|
||||
|
||||
/**
|
||||
* The body of the tag contains nested JSP syntax.
|
||||
* @see #getContentType()
|
||||
*/
|
||||
int CONTENT_TYPE_JSP = CONTENT_TYPE_MIXED;
|
||||
|
||||
/**
|
||||
* The body accepts only template text, EL Expressions, and JSP action elements.
|
||||
* No scripting elements are allowed.
|
||||
*/
|
||||
int CONTENT_TYPE_SCRIPTLESS = 101;
|
||||
|
||||
/**
|
||||
* The body of the tag is interpreted by the tag implementation itself,
|
||||
* and is most likely in a different "language", e.g embedded SQL statements.
|
||||
*/
|
||||
int CONTENT_TYPE_TAG_DEPENDENT = 102;
|
||||
}
|
||||
|
||||
@@ -256,6 +256,13 @@ public class PushController implements Disposable {
|
||||
}
|
||||
|
||||
private boolean isPushAllowed(@NotNull PushSupport<?, ?, ?> pushSupport) {
|
||||
if (mySingleRepoProject) {
|
||||
MyRepoModel repoModel = ContainerUtil.getFirstItem(myView2Model.values());
|
||||
assert repoModel != null;
|
||||
return hasSomethingToPush(myView2Model.keySet()) ||
|
||||
!repoModel.getLoadedCommits().isEmpty() ||
|
||||
myDialog.getAdditionalOptionValue(pushSupport) != null;
|
||||
}
|
||||
Collection<RepositoryNode> nodes = getNodesForSupport(pushSupport);
|
||||
if (pushSupport.getRepositoryManager().isSyncEnabled()) {
|
||||
return hasSomethingToPush(nodes) || (hasCheckedNode(nodes) && allNodesAreLoaded(nodes));
|
||||
@@ -330,6 +337,7 @@ public class PushController implements Disposable {
|
||||
boolean shouldBeSelected;
|
||||
if (!errors.isEmpty()) {
|
||||
shouldBeSelected = false;
|
||||
model.setLoadedCommits(outgoing.getCommits());
|
||||
myPushLog.setChildren(node, ContainerUtil.map(errors, new Function<VcsError, DefaultMutableTreeNode>() {
|
||||
@Override
|
||||
public DefaultMutableTreeNode fun(final VcsError error) {
|
||||
|
||||
@@ -16,371 +16,286 @@
|
||||
package com.intellij.psi.impl;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.io.Bits;
|
||||
import com.intellij.util.io.IntToIntBtree;
|
||||
import com.intellij.util.io.PagedFileStorage;
|
||||
import com.intellij.util.io.RandomAccessDataFile;
|
||||
import gnu.trove.TIntHashSet;
|
||||
import gnu.trove.TIntIntHashMap;
|
||||
import gnu.trove.TIntIntProcedure;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* the (int -> int[]) map which is persisted to the specified file.
|
||||
* the (int -> int[]) map which is persisted to the specified file.<p>
|
||||
* File layout:<p>
|
||||
* <img src="PersistentIntList.png"/>
|
||||
* <p>(to edit the diagram go to www.draw.io, "Import from", this PersistentIntList.png)</p>
|
||||
*/
|
||||
public class PersistentIntList implements Disposable {
|
||||
public static final int MAX_DATA_BYTES = 500000000;
|
||||
public static final int MAX_LIST_LENGTH = 100000;
|
||||
private final IntToIntBtree index;
|
||||
private RandomAccessDataFile data;
|
||||
public static final int MAX_LIST_LENGTH = 10000000;
|
||||
private final FileChannel data;
|
||||
public int gap; // bytes lost due to fragmentation
|
||||
private final int dataStart; // offset of real data; the bytes before are reserved for 'index' meta information, see persistsVarsTo()
|
||||
private IntArray pointers;
|
||||
|
||||
public PersistentIntList(@NotNull File indexFile, @NotNull File dataFile, boolean initial) throws IOException {
|
||||
if (initial) {
|
||||
FileUtil.writeToFile(dataFile, ArrayUtil.EMPTY_BYTE_ARRAY);
|
||||
public PersistentIntList(@NotNull File dataFile, int initialSize) throws IOException {
|
||||
data = new RandomAccessFile(dataFile, "rw").getChannel();
|
||||
int pointersBase;
|
||||
int initialCapacity = initialSize + 256;
|
||||
if (initialSize != 0) {
|
||||
writeInt(data, 0, 4); // base of the pointers array
|
||||
writeInt(data, 4, initialSize);
|
||||
writeInt(data, 8, initialCapacity);
|
||||
fillWithZeros(data, 4 + 8, initialCapacity *4);
|
||||
pointersBase = 4;
|
||||
}
|
||||
PagedFileStorage.StorageLockContext context = new PagedFileStorage.StorageLockContext(true);
|
||||
context.lock();
|
||||
try {
|
||||
data = new RandomAccessDataFile(dataFile);
|
||||
index = new IntToIntBtree(4096, indexFile, context, initial);
|
||||
dataStart = persistsVarsTo(data, initial);
|
||||
else {
|
||||
pointersBase = readInt(data, 0);
|
||||
}
|
||||
finally {
|
||||
context.unlock();
|
||||
pointers = new IntArray(data, pointersBase);
|
||||
if (initialSize != 0) {
|
||||
assert pointers.size == initialSize;
|
||||
assert pointers.capacity == initialCapacity;
|
||||
assert pointers.base == 4;
|
||||
}
|
||||
EMPTY = new Empty(data);
|
||||
}
|
||||
|
||||
public synchronized int getSize() {
|
||||
return pointers.size;
|
||||
}
|
||||
|
||||
private static void fillWithZeros(FileChannel data, int from, int length) throws IOException {
|
||||
ByteBuffer zeros = ByteBuffer.allocateDirect(Math.min(8192, length));
|
||||
|
||||
while (length > 0) {
|
||||
ByteBuffer toWrite = length < zeros.limit() ? ByteBuffer.allocateDirect(length) : zeros;
|
||||
toWrite.position(0);
|
||||
int written = data.write(toWrite, from);
|
||||
length -= written;
|
||||
from += written;
|
||||
}
|
||||
}
|
||||
|
||||
private int persistsVarsTo(@NotNull final RandomAccessDataFile data, boolean toDisk) {
|
||||
return index.persistVars(new IntToIntBtree.BtreeDataStorage() {
|
||||
@Override
|
||||
public int persistInt(int offset, int value, boolean toDisk) {
|
||||
if (toDisk) {
|
||||
data.putInt(offset, value);
|
||||
return value;
|
||||
private static void writeInt(FileChannel data, int off, int value) throws IOException {
|
||||
ByteBuffer b = ByteBuffer.allocate(4);
|
||||
b.putInt(0,value);
|
||||
data.write(b, off);
|
||||
}
|
||||
private static int readInt(FileChannel data, int off) throws IOException {
|
||||
ByteBuffer b = ByteBuffer.allocate(4);
|
||||
int read = data.read(b, off);
|
||||
if (read != 4) throw new IOException(read + " bytes instead of 4");
|
||||
return b.getInt(0);
|
||||
}
|
||||
|
||||
private static class Empty extends IntArray{
|
||||
public Empty(FileChannel data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] toArray() {
|
||||
return ArrayUtil.EMPTY_INT_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
void assertListLength() {
|
||||
}
|
||||
}
|
||||
|
||||
private final Empty EMPTY;
|
||||
|
||||
private static class IntArray {
|
||||
private final FileChannel data;
|
||||
private final int base;
|
||||
private int size;
|
||||
private final int capacity;
|
||||
|
||||
public IntArray(FileChannel data, int base) throws IOException {
|
||||
this.data = data;
|
||||
this.base = base;
|
||||
size = readInt(data, base);
|
||||
capacity = readInt(data, base + 4);
|
||||
assertListLength();
|
||||
}
|
||||
|
||||
private IntArray(FileChannel data) {
|
||||
this.data = data;
|
||||
base = 0;
|
||||
size = 0;
|
||||
capacity = 0;
|
||||
}
|
||||
|
||||
public int get(int i) throws IOException {
|
||||
if (i < 0 || i >= size) throw new IndexOutOfBoundsException("i="+i+"; size="+size);
|
||||
return readInt(data, base + 8 + i*4);
|
||||
}
|
||||
|
||||
public void put(int i, int value) throws IOException {
|
||||
if (i < 0 || i >= size) throw new IndexOutOfBoundsException("i="+i+"; size="+size);
|
||||
writeInt(data, base + 8 + i * 4, value);
|
||||
}
|
||||
|
||||
public IntArray addAll(int[] values) throws IOException {
|
||||
int[] old = toArray();
|
||||
assertSorted(old);
|
||||
assertListLength();
|
||||
|
||||
ByteBuffer mergedBytes = ByteBuffer.allocateDirect(size*4 + values.length * 4);
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
while (i < size || j < values.length) {
|
||||
int stored = i < size ? old[i] : Integer.MAX_VALUE;
|
||||
int value = j < values.length ? values[j] : Integer.MAX_VALUE;
|
||||
if (stored < value) {
|
||||
mergedBytes.putInt(stored);
|
||||
i++;
|
||||
}
|
||||
else if (stored > value) {
|
||||
mergedBytes.putInt(value);
|
||||
j++;
|
||||
}
|
||||
else {
|
||||
return data.getInt(offset);
|
||||
mergedBytes.putInt(value);
|
||||
j++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}, toDisk);
|
||||
mergedBytes.limit(mergedBytes.position());
|
||||
mergedBytes.position(0);
|
||||
|
||||
int[] mergedInts = fromBytes(mergedBytes);
|
||||
assertSorted(mergedInts);
|
||||
|
||||
int newSize = mergedInts.length;
|
||||
if (newSize > capacity) {
|
||||
IntArray realloc = reallocWith(mergedBytes, newSize);
|
||||
assert realloc.size == newSize;
|
||||
return realloc;
|
||||
}
|
||||
data.write(mergedBytes, base + 8);
|
||||
writeInt(data, base, newSize);
|
||||
size = newSize;
|
||||
assertListLength();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private IntArray reallocWith(ByteBuffer bytes, int maxSize) throws IOException {
|
||||
assert maxSize > 0 && maxSize < MAX_LIST_LENGTH : maxSize;
|
||||
int newSize = Math.max(maxSize, bytes.limit() / 4);
|
||||
int newCapacity = newSize < 10 ? (newSize + 1) * 2 : newSize * 3 / 2;
|
||||
int newBase = (int)data.size();
|
||||
writeInt(data, newBase, newSize);
|
||||
writeInt(data, newBase + 4, newCapacity);
|
||||
bytes.position(0);
|
||||
data.write(bytes, newBase + 8);
|
||||
fillWithZeros(data, newBase + 8 + newSize * 4, (newCapacity - newSize) * 4);
|
||||
IntArray array = new IntArray(data, newBase);
|
||||
assert array.size == newSize;
|
||||
assert array.capacity == newCapacity;
|
||||
assert array.base == newBase;
|
||||
array.assertListLength();
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
public int[] toArray() throws IOException {
|
||||
return fromBytes(toBuffer());
|
||||
}
|
||||
|
||||
private ByteBuffer toBuffer() throws IOException {
|
||||
assertListLength();
|
||||
int listLength = size;
|
||||
ByteBuffer bytes = ByteBuffer.allocateDirect(listLength * 4);
|
||||
int read = data.read(bytes, base+8);
|
||||
if (read != listLength*4) throw new IOException(read +" instead of "+listLength*4);
|
||||
bytes.position(0);
|
||||
assert bytes.limit() == listLength * 4;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
void assertListLength() {
|
||||
int listLength = size;
|
||||
assert 0 <= listLength && listLength <= MAX_LIST_LENGTH : "size = "+listLength + ", capacity=" + capacity;
|
||||
assert 0 < capacity && capacity <= MAX_LIST_LENGTH : "size = "+listLength + ", capacity=" + capacity;
|
||||
assert capacity >= listLength : "size = "+listLength + ", capacity=" + capacity;
|
||||
assert listLength == 0 || capacity <= (listLength+1)*2 : "size = "+listLength + ", capacity=" + capacity;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
index.withStorageLock(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
persistsVarsTo(data, true);
|
||||
index.doClose();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
data.dispose();
|
||||
}
|
||||
});
|
||||
try {
|
||||
data.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public int[] get(final int id) {
|
||||
final Ref<int[]> res = new Ref<int[]>();
|
||||
|
||||
index.withStorageLock(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final int[] ptrPtr = new int[1];
|
||||
boolean exists = index.get(id, ptrPtr);
|
||||
if (!exists) {
|
||||
ptrPtr[0] = 0;
|
||||
}
|
||||
int pointer = ptrPtr[0];
|
||||
if (pointer == 0) {
|
||||
res.set(ArrayUtil.EMPTY_INT_ARRAY);
|
||||
}
|
||||
else {
|
||||
assertPointer(pointer);
|
||||
int listLength = data.getInt(pointer);
|
||||
int capacity = data.getInt(pointer + 4);
|
||||
assertListLength(listLength, capacity);
|
||||
int[] result = new int[listLength];
|
||||
byte[] bytes = new byte[listLength * 4];
|
||||
data.get(pointer + 8, bytes, 0, bytes.length);
|
||||
for (int i = 0; i < listLength; i++) {
|
||||
result[i] = Bits.getInt(bytes, i*4);
|
||||
}
|
||||
res.set(result);
|
||||
}
|
||||
}
|
||||
});
|
||||
return res.get();
|
||||
public synchronized int[] get(final int id) {
|
||||
assertPointer(id);
|
||||
try {
|
||||
int arrayBase = pointers.get(id);
|
||||
IntArray array = arrayBase == 0 ? EMPTY : new IntArray(data, arrayBase);
|
||||
return array.toArray();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
// return true if was added
|
||||
public boolean add(final int id, final int value) {
|
||||
assert value > 0;
|
||||
assert id > 0;
|
||||
final boolean[] added = new boolean[1];
|
||||
index.withStorageLock(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int[] ptrPtr = new int[1];
|
||||
index.get(id, ptrPtr);
|
||||
final int pointer = ptrPtr[0];
|
||||
int[] stored;
|
||||
int capacity;
|
||||
final int listLength;
|
||||
if (pointer == 0) {
|
||||
stored = ArrayUtil.EMPTY_INT_ARRAY;
|
||||
listLength = 0;
|
||||
capacity = 2;
|
||||
}
|
||||
else {
|
||||
assertPointer(pointer);
|
||||
listLength = data.getInt(pointer);
|
||||
capacity = data.getInt(pointer+4);
|
||||
assertListLength(listLength,capacity);
|
||||
stored = new int[listLength];
|
||||
for (int i = 0; i < listLength; i++) {
|
||||
int v = data.getInt(pointer + (i + 2) * 4);
|
||||
stored[i] = v;
|
||||
if (v == value) return;
|
||||
}
|
||||
// append
|
||||
if (capacity > listLength /*|| data.length() == pointer + 4 + 4 + 4*capacity*/) {
|
||||
data.putInt(pointer + (listLength + 2) * 4, value);
|
||||
data.putInt(pointer, listLength + 1);
|
||||
if (capacity <= listLength) {
|
||||
data.putInt(pointer+4, capacity + 1);
|
||||
}
|
||||
added[0] = true;
|
||||
return;
|
||||
}
|
||||
// reallocate
|
||||
gap += 4 + 4 + 4 * capacity;
|
||||
}
|
||||
|
||||
int storePointer = (int)data.length();
|
||||
data.putInt(storePointer, stored.length + 1);
|
||||
int newCapacity = capacity < 10 ? capacity * 2 : (int)(capacity * 1.5);
|
||||
assert newCapacity > stored.length + 1;
|
||||
data.putInt(storePointer+4, newCapacity);
|
||||
for (int i = 0; i < stored.length; i++) {
|
||||
int v = stored[i];
|
||||
data.putInt(storePointer + (i+2)*4, v);
|
||||
}
|
||||
data.putInt(storePointer + (stored.length+2)*4, value);
|
||||
for (int i = stored.length + 1; i < newCapacity; i++) {
|
||||
data.putInt(storePointer + (i+2)*4, 0); // gap
|
||||
}
|
||||
index.put(id, storePointer);
|
||||
if (storePointer > 10000000) {
|
||||
int i = 0;
|
||||
}
|
||||
added[0] = true;
|
||||
}
|
||||
});
|
||||
|
||||
return added[0];
|
||||
}
|
||||
|
||||
private static void assertListLength(int listLength, int capacity) {
|
||||
assert 0 < listLength && listLength <= MAX_LIST_LENGTH : listLength;
|
||||
assert 0 < capacity && capacity <= MAX_LIST_LENGTH : capacity;
|
||||
assert capacity >= listLength : listLength + ", " + capacity;
|
||||
assert capacity <= (listLength+1)*2 : listLength + ", " + capacity;
|
||||
}
|
||||
|
||||
public void addAll(final int id, @NotNull final int[] values) {
|
||||
assertListLength(values.length, values.length);
|
||||
public synchronized void addAll(final int id, @NotNull final int[] values) {
|
||||
assert 0 < values.length && values.length <= MAX_LIST_LENGTH : values.length;
|
||||
assert id > 0;
|
||||
Arrays.sort(values);
|
||||
|
||||
index.withStorageLock(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int[] ptrPtr = new int[1];
|
||||
index.get(id, ptrPtr);
|
||||
final int pointer = ptrPtr[0];
|
||||
int capacity;
|
||||
final int newListLength;
|
||||
byte[] mergedBytes;
|
||||
|
||||
if (pointer == 0) {
|
||||
mergedBytes = toBytes(values);
|
||||
newListLength = values.length;
|
||||
capacity = 0;
|
||||
}
|
||||
else {
|
||||
int[] oldIds = get(id);
|
||||
checkSorted(oldIds);
|
||||
|
||||
assertPointer(pointer);
|
||||
int storedListLength = data.getInt(pointer);
|
||||
capacity = data.getInt(pointer + 4);
|
||||
assertListLength(storedListLength, capacity);
|
||||
// try to merge inplace and if failed, reallocate at the end
|
||||
byte[] storedBytes = new byte[storedListLength * 4];
|
||||
data.get(pointer + 8, storedBytes, 0, storedListLength * 4);
|
||||
|
||||
mergedBytes = new byte[storedBytes.length + values.length * 4];
|
||||
int outPtr = 0;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
while (i < storedListLength || j < values.length) {
|
||||
int stored = i < storedListLength ? Bits.getInt(storedBytes, i * 4) : Integer.MAX_VALUE;
|
||||
int value = j < values.length ? values[j] : Integer.MAX_VALUE;
|
||||
if (stored < value) {
|
||||
Bits.putInt(mergedBytes, outPtr, stored);
|
||||
outPtr += 4;
|
||||
i++;
|
||||
}
|
||||
else if (stored > value) {
|
||||
Bits.putInt(mergedBytes, outPtr, value);
|
||||
outPtr += 4;
|
||||
j++;
|
||||
}
|
||||
else {
|
||||
Bits.putInt(mergedBytes, outPtr, value);
|
||||
outPtr += 4;
|
||||
j++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
int[] mergedInts = fromBytes(mergedBytes, outPtr);
|
||||
checkSorted(mergedInts);
|
||||
|
||||
newListLength = outPtr / 4;
|
||||
assertListLength(newListLength, newListLength);
|
||||
if (newListLength <= capacity) {
|
||||
storeArray(data, pointer, newListLength, capacity, mergedBytes);
|
||||
return;
|
||||
}
|
||||
gap += capacity * 4 + 8;
|
||||
}
|
||||
// reallocate at the end
|
||||
|
||||
int storePointer = (int)data.length();
|
||||
assertPointer(storePointer);
|
||||
int oldCapacity = Math.max(capacity, newListLength);
|
||||
int newCapacity = oldCapacity < 10 ? (oldCapacity + 1) * 2 : (int)(oldCapacity * 1.5);
|
||||
assert newCapacity > newListLength + 1;
|
||||
storeArray(data, storePointer, newListLength, newCapacity, mergedBytes);
|
||||
index.put(id, storePointer);
|
||||
try {
|
||||
if (id >= pointers.size) {
|
||||
pointers = pointers.reallocWith(pointers.toBuffer(), id+1);
|
||||
writeInt(data, 0, pointers.base);
|
||||
assert pointers.size > id : id + " > " + pointers.size;
|
||||
}
|
||||
});
|
||||
int arrayBase = pointers.get(id);
|
||||
IntArray array = arrayBase == 0 ? EMPTY : new IntArray(data, arrayBase);
|
||||
IntArray newArray = array.addAll(values);
|
||||
if (newArray != null) {
|
||||
pointers.put(id, newArray.base);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
int[] ids = get(id);
|
||||
checkSorted(ids);
|
||||
assertSorted(ids);
|
||||
TIntHashSet set = new TIntHashSet(ids);
|
||||
assert set.containsAll(values): "ids: "+Arrays.toString(ids)+";\n values:"+Arrays.toString(values);
|
||||
}
|
||||
|
||||
private static void checkSorted(int[] oldIds) {
|
||||
private static void assertSorted(int[] oldIds) {
|
||||
for (int i = 1; i < oldIds.length; i++) {
|
||||
assert oldIds[i - 1] < oldIds[i] : oldIds[i-1] + ", " + oldIds[i];
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] toBytes(@NotNull int[] values) {
|
||||
byte[] mergedBytes = new byte[4 * values.length];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
int value = values[i];
|
||||
Bits.putInt(mergedBytes, i * 4, value);
|
||||
}
|
||||
return mergedBytes;
|
||||
}
|
||||
|
||||
private static int[] fromBytes(@NotNull byte[] bytes, int length) {
|
||||
assert length % 4 == 0;
|
||||
int[] ints = new int[length/4];
|
||||
for (int i = 0; i < length; i+=4) {
|
||||
int value = Bits.getInt(bytes, i);
|
||||
ints[i/4] = value;
|
||||
}
|
||||
return ints;
|
||||
}
|
||||
|
||||
private static void storeArray(@NotNull RandomAccessDataFile data,
|
||||
int storePointer,
|
||||
int newListLength,
|
||||
int newCapacity,
|
||||
@NotNull byte[] mergedBytes) {
|
||||
assertListLength(newListLength, newCapacity);
|
||||
data.putInt(storePointer, newListLength);
|
||||
data.putInt(storePointer + 4, newCapacity);
|
||||
data.put(storePointer + 8, mergedBytes, 0, newListLength * 4);
|
||||
byte[] fill = new byte[(newCapacity - newListLength) * 4];
|
||||
Arrays.fill(fill, (byte)-1);
|
||||
data.put(storePointer + 8 + newListLength * 4, fill, 0, fill.length);
|
||||
private static int[] fromBytes(@NotNull ByteBuffer bytes) {
|
||||
IntBuffer intBuffer = bytes.asIntBuffer();
|
||||
int[] result = new int[intBuffer.limit()];
|
||||
intBuffer.get(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void assertPointer(int pointer) {
|
||||
assert 0 < pointer && pointer <= MAX_DATA_BYTES : pointer;
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
index.withStorageLock(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
persistsVarsTo(data, true);
|
||||
index.doFlush();
|
||||
data.sync();
|
||||
//data.force();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void compactIfNecessary() {
|
||||
if (gap < data.length() / 2) return;
|
||||
index.withStorageLock(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
persistsVarsTo(data, true);
|
||||
index.doFlush();
|
||||
data.sync();
|
||||
|
||||
try {
|
||||
final RandomAccessDataFile newData = new RandomAccessDataFile(new File(data.getFile().getParentFile(), "newData"));
|
||||
persistsVarsTo(newData, true);
|
||||
final TIntIntHashMap map = new TIntIntHashMap();
|
||||
index.processMappings(new IntToIntBtree.KeyValueProcessor() {
|
||||
@Override
|
||||
public boolean process(int key, int value) throws IOException {
|
||||
map.put(key, value);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
map.forEachEntry(new TIntIntProcedure() {
|
||||
@Override
|
||||
public boolean execute(int key, int value) {
|
||||
int[] ids = get(key);
|
||||
int pointer = (int)newData.length();
|
||||
byte[] bytes = toBytes(ids);
|
||||
storeArray(newData, pointer, ids.length, (int)(ids.length * 1.3), bytes);
|
||||
index.put(key, pointer);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
data.dispose();
|
||||
data = newData;
|
||||
gap = 0;
|
||||
flush();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
public synchronized void flush() throws IOException {
|
||||
data.force(true);
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
+26
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -42,6 +42,7 @@ import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.ex.WindowManagerEx;
|
||||
import com.intellij.pom.Navigatable;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -54,6 +55,7 @@ import com.intellij.ui.components.JBLayeredPane;
|
||||
import com.intellij.ui.components.JBScrollPane;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.io.URLUtil;
|
||||
import com.intellij.util.ui.GraphicsUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -66,8 +68,11 @@ import javax.swing.event.ChangeListener;
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import javax.swing.event.HyperlinkListener;
|
||||
import javax.swing.text.*;
|
||||
import javax.swing.text.html.HTMLDocument;
|
||||
import javax.swing.text.html.HTMLEditorKit;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
@@ -155,6 +160,11 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
myIsShown = false;
|
||||
|
||||
myEditorPane = new JEditorPane(UIUtil.HTML_MIME, "") {
|
||||
@Override
|
||||
public EditorKit getEditorKit() {
|
||||
return new HTMLEditorKit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredScrollableViewportSize() {
|
||||
if (getWidth() == 0 || getHeight() == 0) {
|
||||
@@ -529,7 +539,6 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
}
|
||||
|
||||
private void setDataInternal(SmartPsiElementPointer element, String text, final Rectangle viewRect, boolean skip) {
|
||||
|
||||
myElement = element;
|
||||
|
||||
boolean justShown = false;
|
||||
@@ -549,6 +558,21 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
myText = text;
|
||||
}
|
||||
|
||||
Document document = myEditorPane.getDocument();
|
||||
if (document instanceof HTMLDocument && element != null) {
|
||||
// set base URL for this javadoc to resolve relative images correctly
|
||||
VirtualFile virtualFile = element.getVirtualFile();
|
||||
VirtualFile directory = virtualFile == null ? null : virtualFile.getParent();
|
||||
String path = directory == null ? "" : directory.getPath()+"/";
|
||||
|
||||
try {
|
||||
URL url = new URL(URLUtil.FILE_PROTOCOL, null, path);
|
||||
((HTMLDocument)document).setBase(url);
|
||||
}
|
||||
catch (MalformedURLException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
//noinspection SSBasedInspection
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -36,9 +36,9 @@ import java.util.zip.ZipFile;
|
||||
* Date: 3/25/11
|
||||
*/
|
||||
public class UrlUtil {
|
||||
private static final String JAR_SEPARATOR = "!/";
|
||||
private static final String JAR_SEPARATOR = URLUtil.JAR_SEPARATOR;
|
||||
private static final String URL_PATH_SEPARATOR = "/";
|
||||
private static final String FILE_PROTOCOL = "file";
|
||||
private static final String FILE_PROTOCOL = URLUtil.FILE_PROTOCOL;
|
||||
private static final String FILE_PROTOCOL_PREFIX = FILE_PROTOCOL + ":";
|
||||
|
||||
public static String loadText(URL url) throws IOException {
|
||||
@@ -56,7 +56,7 @@ public class UrlUtil {
|
||||
if ("jar".equalsIgnoreCase(protocol)) {
|
||||
return getChildPathsFromJar(root);
|
||||
}
|
||||
if ("file".equalsIgnoreCase(protocol)){
|
||||
if (FILE_PROTOCOL.equalsIgnoreCase(protocol)){
|
||||
return getChildPathsFromFile(root);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
|
||||
+14
-21
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -16,46 +16,39 @@
|
||||
|
||||
package com.intellij.openapi.editor.actions;
|
||||
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.actionSystem.ToggleAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Dmitry Avdeev
|
||||
*/
|
||||
public class ToggleShowImportPopupsAction extends ToggleAction {
|
||||
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
return getAnalyzer(e).isImportHintsEnabled(getFile(e));
|
||||
PsiFile file = getFile(e);
|
||||
return file != null && DaemonCodeAnalyzer.getInstance(file.getProject()).isImportHintsEnabled(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
getAnalyzer(e).setImportHintsEnabled(getFile(e), state);
|
||||
PsiFile file = getFile(e);
|
||||
if (file != null) {
|
||||
DaemonCodeAnalyzer.getInstance(file.getProject()).setImportHintsEnabled(file, state);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
if (getFile(e) == null) {
|
||||
e.getPresentation().setEnabled(false);
|
||||
e.getPresentation().setVisible(false);
|
||||
}
|
||||
else {
|
||||
e.getPresentation().setEnabled(true);
|
||||
e.getPresentation().setVisible(true);
|
||||
super.update(e);
|
||||
}
|
||||
}
|
||||
|
||||
private DaemonCodeAnalyzer getAnalyzer(AnActionEvent e) {
|
||||
return DaemonCodeAnalyzer.getInstance(e.getData(CommonDataKeys.PROJECT));
|
||||
public void update(@NotNull AnActionEvent e) {
|
||||
boolean works = getFile(e) != null;
|
||||
e.getPresentation().setEnabled(works);
|
||||
e.getPresentation().setVisible(works);
|
||||
super.update(e);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.openapi.actionSystem;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -23,8 +24,8 @@ import javax.swing.*;
|
||||
* An action which has a selected state, and which toggles its selected state when performed.
|
||||
* Can be used to represent a menu item with a checkbox, or a toolbar button which keeps its pressed state.
|
||||
*/
|
||||
@SuppressWarnings("StaticInheritance")
|
||||
public abstract class ToggleAction extends AnAction implements Toggleable {
|
||||
|
||||
public ToggleAction(){
|
||||
}
|
||||
|
||||
@@ -37,7 +38,7 @@ public abstract class ToggleAction extends AnAction implements Toggleable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void actionPerformed(final AnActionEvent e){
|
||||
public final void actionPerformed(@NotNull final AnActionEvent e){
|
||||
final boolean state = !isSelected(e);
|
||||
setSelected(e, state);
|
||||
final Boolean selected = state ? Boolean.TRUE : Boolean.FALSE;
|
||||
@@ -60,8 +61,8 @@ public abstract class ToggleAction extends AnAction implements Toggleable {
|
||||
public abstract void setSelected(AnActionEvent e, boolean state);
|
||||
|
||||
@Override
|
||||
public void update(final AnActionEvent e){
|
||||
final Boolean selected = isSelected(e) ? Boolean.TRUE : Boolean.FALSE;
|
||||
public void update(@NotNull final AnActionEvent e){
|
||||
boolean selected = isSelected(e);
|
||||
final Presentation presentation = e.getPresentation();
|
||||
presentation.putClientProperty(SELECTED_PROPERTY, selected);
|
||||
}
|
||||
|
||||
+13
-26
@@ -76,7 +76,6 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
private static final int FREE_PAINTERS_AREA_WIDTH = 5;
|
||||
private static final int GAP_BETWEEN_ICONS = 3;
|
||||
private static final TooltipGroup GUTTER_TOOLTIP_GROUP = new TooltipGroup("GUTTER_TOOLTIP_GROUP", 0);
|
||||
private static final Color COLOR_F0F0 = new Color(0xF0F0F0);
|
||||
public static final TIntFunction ID = new TIntFunction() {
|
||||
@Override
|
||||
public int execute(int value) {
|
||||
@@ -96,7 +95,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
private TIntArrayList myTextAnnotationGutterSizes = new TIntArrayList();
|
||||
private ArrayList<TextAnnotationGutterProvider> myTextAnnotationGutters = new ArrayList<TextAnnotationGutterProvider>();
|
||||
private final Map<TextAnnotationGutterProvider, EditorGutterAction> myProviderToListener = new HashMap<TextAnnotationGutterProvider, EditorGutterAction>();
|
||||
private static final int GAP_BETWEEN_ANNOTATIONS = 6;
|
||||
private static final int GAP_BETWEEN_ANNOTATIONS = 5;
|
||||
private Color myBackgroundColor = null;
|
||||
private String myLastGutterToolTip = null;
|
||||
private int myLastPreferredHeight = -1;
|
||||
@@ -227,7 +226,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
|
||||
private void paintEditorBackgrounds(Graphics g, Rectangle clip, int firstVisibleOffset, int lastVisibleOffset) {
|
||||
Color defaultBackgroundColor = myEditor.getBackgroundColor();
|
||||
int startX = getWhitespaceSeparatorOffset() + 1;
|
||||
int startX = getWhitespaceSeparatorOffset() + (isFoldingOutlineShown() ? 1 : 0);
|
||||
IterationState state = new IterationState(myEditor, firstVisibleOffset, lastVisibleOffset, false, true);
|
||||
while (!state.atEnd()) {
|
||||
VisualPosition visualStart = myEditor.offsetToVisualPosition(state.getStartOffset());
|
||||
@@ -329,19 +328,12 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
|
||||
x += myTextAnnotationGutterSizes.get(i);
|
||||
}
|
||||
|
||||
if (!myEditor.isInDistractionFreeMode()) {
|
||||
UIUtil.drawVDottedLine((Graphics2D)g, getAnnotationsAreaOffset() + w - 1, clip.y, clip.y + clip.height, null, getOutlineColor(false));
|
||||
}
|
||||
}
|
||||
|
||||
private void paintFoldingTree(Graphics g, Rectangle clip, int firstVisibleOffset, int lastVisibleOffset) {
|
||||
if (isFoldingOutlineShown()) {
|
||||
doPaintFoldingTree((Graphics2D)g, clip, firstVisibleOffset, lastVisibleOffset);
|
||||
}
|
||||
else {
|
||||
UIUtil.drawVDottedLine((Graphics2D)g, clip.x + clip.width - 1, clip.y, clip.y + clip.height, null, getOutlineColor(false));
|
||||
}
|
||||
}
|
||||
|
||||
private void paintLineMarkers(Graphics g, Rectangle clip, int firstVisibleOffset, int lastVisibleOffset) {
|
||||
@@ -378,8 +370,6 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
|
||||
private void paintLineNumbers(Graphics g, Rectangle clip) {
|
||||
if (isLineNumbersShown()) {
|
||||
int x = getLineNumberAreaOffset() + getLineNumberAreaWidth() - 2;
|
||||
UIUtil.drawVDottedLine((Graphics2D)g, x, clip.y, clip.y + clip.height, null, getOutlineColor(false));
|
||||
doPaintLineNumbers(g, clip);
|
||||
}
|
||||
}
|
||||
@@ -396,7 +386,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
EditorColorsScheme colorsScheme = myEditor.getColorsScheme();
|
||||
boolean distractionMode = myEditor.isInDistractionFreeMode();
|
||||
Color color = distractionMode ? colorsScheme.getDefaultBackground() : colorsScheme.getColor(EditorColors.GUTTER_BACKGROUND);
|
||||
myBackgroundColor = color == null ? COLOR_F0F0 : color;
|
||||
myBackgroundColor = color == null ? EditorColors.GUTTER_BACKGROUND.getDefaultColor() : color;
|
||||
}
|
||||
return myBackgroundColor;
|
||||
}
|
||||
@@ -648,9 +638,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
}
|
||||
});
|
||||
|
||||
myLineMarkerAreaWidth = myIconsAreaWidth + FREE_PAINTERS_AREA_WIDTH +
|
||||
// if folding outline is shown, there will be enough place for change markers, otherwise add place for it.
|
||||
(isFoldingOutlineShown() ? 0 : getFoldingAnchorWidth() / 2);
|
||||
myLineMarkerAreaWidth = myIconsAreaWidth + FREE_PAINTERS_AREA_WIDTH;
|
||||
}
|
||||
|
||||
private void paintGutterRenderers(final Graphics g, int firstVisibleOffset, int lastVisibleOffset) {
|
||||
@@ -739,7 +727,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
|
||||
int height = endY - startY;
|
||||
int w = FREE_PAINTERS_AREA_WIDTH;
|
||||
int x = getLineMarkerAreaOffset() + myIconsAreaWidth;
|
||||
int x = getLineMarkerAreaOffset() + myIconsAreaWidth - 1;
|
||||
return new Rectangle(x, startY, w, height);
|
||||
}
|
||||
|
||||
@@ -770,7 +758,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
|
||||
final int leftSize = x - getLineMarkerAreaOffset();
|
||||
|
||||
x = getLineMarkerAreaOffset() + myIconsAreaWidth;
|
||||
x = getLineMarkerAreaOffset() + myIconsAreaWidth - 2; // because of 2px LineMarkerRenderers
|
||||
for (GutterMark r : row) {
|
||||
if (((GutterIconRenderer)r).getAlignment() == GutterIconRenderer.Alignment.RIGHT) {
|
||||
Icon icon = r.getIcon();
|
||||
@@ -780,7 +768,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
}
|
||||
}
|
||||
|
||||
int rightSize = myIconsAreaWidth + getLineMarkerAreaOffset() - x;
|
||||
int rightSize = myIconsAreaWidth + getLineMarkerAreaOffset() - x + 1;
|
||||
|
||||
if (middleCount > 0) {
|
||||
middleSize -= GAP_BETWEEN_ICONS;
|
||||
@@ -845,7 +833,9 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
private void paintFoldingLines(final Graphics2D g, final Rectangle clip) {
|
||||
if (!isFoldingOutlineShown()) return;
|
||||
|
||||
UIUtil.drawVDottedLine(g, getWhitespaceSeparatorOffset(), clip.y, clip.y + clip.height, null, getOutlineColor(false));
|
||||
g.setColor(getOutlineColor(false));
|
||||
int x = getWhitespaceSeparatorOffset();
|
||||
UIUtil.drawLine(g, x, clip.y, x, clip.y + clip.height);
|
||||
|
||||
final int anchorX = getFoldingAreaOffset();
|
||||
final int width = getFoldingAnchorWidth();
|
||||
@@ -981,14 +971,11 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
}
|
||||
|
||||
public int getFoldingAreaOffset() {
|
||||
return getLineMarkerAreaOffset() +
|
||||
getLineMarkerAreaWidth();
|
||||
return getLineMarkerAreaOffset() + getLineMarkerAreaWidth();
|
||||
}
|
||||
|
||||
public int getFoldingAreaWidth() {
|
||||
return isFoldingOutlineShown()
|
||||
? getFoldingAnchorWidth() + 2
|
||||
: 0;
|
||||
return getFoldingAnchorWidth() + (isFoldingOutlineShown() ? 2 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1347,7 +1334,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
closeAllAnnotations();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,7 +303,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
private final TIntFunction myLineNumberAreaWidthFunction = new TIntFunction() {
|
||||
@Override
|
||||
public int execute(int lineNumber) {
|
||||
return getFontMetrics(Font.PLAIN).stringWidth(Integer.toString(lineNumber + 1)) + 6;
|
||||
return getFontMetrics(Font.PLAIN).stringWidth(Integer.toString(lineNumber + 1)) + 5;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -6771,10 +6771,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
g.setColor(ButtonlessScrollBarUI.getTrackBackground());
|
||||
g.fillRect(0, 0, width, height);
|
||||
|
||||
int shortner = 0;
|
||||
if (myGutterComponent.isFoldingOutlineShown()) {
|
||||
shortner = myGutterComponent.getFoldingAreaWidth() / 2;
|
||||
}
|
||||
int shortner = myGutterComponent.getFoldingAreaWidth() / 2;
|
||||
|
||||
g.setColor(myGutterComponent.getBackground());
|
||||
g.fillRect(0, 0, width - shortner, height);
|
||||
|
||||
+2
-12
@@ -36,7 +36,6 @@ import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.FocusWatcher;
|
||||
import com.intellij.ui.PrevNextActionsDescriptor;
|
||||
import com.intellij.ui.SideBorder;
|
||||
import com.intellij.ui.TabbedPaneWrapper;
|
||||
import com.intellij.ui.tabs.UiDecorator;
|
||||
import com.intellij.util.SmartList;
|
||||
@@ -351,7 +350,7 @@ public abstract class EditorComposite implements Disposable {
|
||||
if (remove) {
|
||||
container.remove(component.getParent());
|
||||
} else {
|
||||
container.add(new TopBottomComponentWrapper(component, top));
|
||||
container.add(new TopBottomComponentWrapper(component));
|
||||
}
|
||||
container.revalidate();
|
||||
}
|
||||
@@ -474,19 +473,10 @@ public abstract class EditorComposite implements Disposable {
|
||||
private static class TopBottomComponentWrapper extends JPanel {
|
||||
private final JComponent myWrappee;
|
||||
|
||||
public TopBottomComponentWrapper(JComponent component, boolean top) {
|
||||
public TopBottomComponentWrapper(JComponent component) {
|
||||
super(new BorderLayout());
|
||||
myWrappee = component;
|
||||
setOpaque(false);
|
||||
|
||||
setBorder(new SideBorder(null, top ? SideBorder.BOTTOM : SideBorder.TOP, true) {
|
||||
@Override
|
||||
public Color getLineColor() {
|
||||
Color result = EditorColorsManager.getInstance().getGlobalScheme().getColor(EditorColors.TEARLINE_COLOR);
|
||||
return result == null ? Color.black : result;
|
||||
}
|
||||
});
|
||||
|
||||
add(component);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ class ToolWindowsWidget extends JLabel implements CustomStatusBarWidget, StatusB
|
||||
private JBPopup popup;
|
||||
private boolean wasExited = false;
|
||||
|
||||
ToolWindowsWidget(Disposable parent) {
|
||||
ToolWindowsWidget(@NotNull Disposable parent) {
|
||||
new BaseButtonBehavior(this, TimedDeadzone.NULL) {
|
||||
@Override
|
||||
protected void execute(MouseEvent e) {
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
<option name="ANNOTATIONS_COLOR" value="000080" />
|
||||
<option name="ANNOTATIONS_MERGED_COLOR" value="008080" />
|
||||
<option name="CARET_COLOR" value="0"/>
|
||||
<option name="RIGHT_MARGIN_COLOR" value="c0c0c0"/>
|
||||
<option name="RIGHT_MARGIN_COLOR" value="E0E0E0"/>
|
||||
<option name="SOFT_WRAP_SIGN_COLOR" value="c0c0c0"/>
|
||||
<option name="TEARLINE_COLOR" value="808080"/>
|
||||
<option name="SELECTED_TEARLINE_COLOR" value="000000"/>
|
||||
<option name="TEARLINE_COLOR" value="D0D0D0"/>
|
||||
<option name="SELECTED_TEARLINE_COLOR" value="9C9C9C"/>
|
||||
<option name="READONLY_FRAGMENT_BACKGROUND" value="cfe7ff"/>
|
||||
|
||||
<option name="ADDED_LINES_COLOR" value="CBE3CA"/>
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
<programRunner implementation="com.intellij.execution.runners.BasicProgramRunner" order="last"/>
|
||||
|
||||
<projectConfigurable groupId="editor" groupWeight="160" displayName="Inspections" provider="com.intellij.profile.codeInspection.ui.ProjectInspectionToolsConfigurableProvider" order="before preferences.intentionPowerPack"/>
|
||||
<projectConfigurable groupId="appearance" groupWeight="200" instance="com.intellij.ide.util.scopeChooser.ScopeChooserConfigurable" id="project.scopes" key="scopes.display.name" bundle="messages.IdeBundle" />
|
||||
<projectConfigurable groupId="appearance" groupWeight="111" instance="com.intellij.ide.util.scopeChooser.ScopeChooserConfigurable" id="project.scopes" key="scopes.display.name" bundle="messages.IdeBundle" />
|
||||
|
||||
<checkoutCompletedListener implementation="com.intellij.openapi.vcs.checkout.PlatformProjectCheckoutListener" id="PlatformProjectCheckoutListener"/>
|
||||
|
||||
|
||||
+2
-3
@@ -407,7 +407,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
|
||||
@Override
|
||||
public long checkHighlighting(final boolean checkWarnings, final boolean checkInfos, final boolean checkWeakWarnings, boolean ignoreExtraHighlighting) {
|
||||
try {
|
||||
return collectAndCheckHighlighting(checkWarnings, checkInfos, checkWeakWarnings);
|
||||
return collectAndCheckHighlighting(checkWarnings, checkInfos, checkWeakWarnings, ignoreExtraHighlighting);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
@@ -1501,8 +1501,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
|
||||
private long collectAndCheckHighlighting(boolean checkWarnings, boolean checkInfos, boolean checkWeakWarnings,
|
||||
boolean ignoreExtraHighlighting) throws Exception {
|
||||
ExpectedHighlightingData data = new ExpectedHighlightingData(myEditor.getDocument(),
|
||||
checkWarnings, checkWeakWarnings, ignoreExtraHighlighting,
|
||||
checkInfos, getHostFile());
|
||||
checkWarnings, checkWeakWarnings, checkInfos, ignoreExtraHighlighting, getHostFile());
|
||||
data.init();
|
||||
return collectAndCheckHighlighting(data);
|
||||
}
|
||||
|
||||
@@ -50,9 +50,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
* @author Wilfried Middleton
|
||||
* @version 5.3, January 10, 2007
|
||||
*/
|
||||
@SuppressWarnings("AssignmentToForLoopParameter")
|
||||
@SuppressWarnings({"AssignmentToForLoopParameter","UnnecessaryThis"})
|
||||
public final class ImmutableText extends ImmutableCharSequence implements CharArrayExternalizable {
|
||||
|
||||
/**
|
||||
* Holds the default size for primitive blocks of characters.
|
||||
*/
|
||||
@@ -82,18 +81,39 @@ public final class ImmutableText extends ImmutableCharSequence implements CharAr
|
||||
}
|
||||
|
||||
private static ImmutableText valueOf(@NotNull CharSequence str) {
|
||||
return new ImmutableText(new LeafNode(CharArrayUtil.fromSequence(str, 0, str.length())));
|
||||
return new ImmutableText(createLeafNode(CharArrayUtil.fromSequence(str, 0, str.length())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text that contains the characters from the specified
|
||||
* Returns the text that contains the characters from the specified
|
||||
* array.
|
||||
*
|
||||
* @param chars the array source of the characters.
|
||||
* @return the corresponding instance.
|
||||
*/
|
||||
public static ImmutableText valueOf(@NotNull char[] chars) {
|
||||
return new ImmutableText(new LeafNode(chars));
|
||||
return new ImmutableText(createLeafNode(chars));
|
||||
}
|
||||
|
||||
private static LeafNode createLeafNode(@NotNull char[] chars) {
|
||||
if (chars.length == 0) {
|
||||
return EMPTY_NODE;
|
||||
}
|
||||
|
||||
byte[] packed = new byte[chars.length];
|
||||
boolean success = true;
|
||||
for (int i=0; i<chars.length;i++) {
|
||||
char c = chars[i];
|
||||
if (c >= 256) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
packed[i] = (byte)c;
|
||||
}
|
||||
if (success) {
|
||||
return new Leaf8BitNode(packed);
|
||||
}
|
||||
return new WideLeafNode(chars);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,26 +125,20 @@ public final class ImmutableText extends ImmutableCharSequence implements CharAr
|
||||
*/
|
||||
public ImmutableText ensureChunked() {
|
||||
if (length() > BLOCK_SIZE && myNode instanceof LeafNode) {
|
||||
return new ImmutableText(nodeOf(((LeafNode)myNode)._data, 0, length()));
|
||||
return new ImmutableText(nodeOf((LeafNode)myNode, 0, length()));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private static Node nodeOf(@NotNull char[] chars, int offset, int length) {
|
||||
private static Node nodeOf(@NotNull LeafNode node, int offset, int length) {
|
||||
if (length <= BLOCK_SIZE) {
|
||||
if (offset == 0 && length == chars.length) {
|
||||
return new LeafNode(chars);
|
||||
}
|
||||
char[] subArray = new char[length];
|
||||
System.arraycopy(chars, offset, subArray, 0, length);
|
||||
return new LeafNode(subArray);
|
||||
} else { // Splits on a block boundary.
|
||||
int half = ((length + BLOCK_SIZE) >> 1) & BLOCK_MASK;
|
||||
return new CompositeNode(nodeOf(chars, offset, half), nodeOf(chars, offset + half, length - half));
|
||||
return node.subNode(offset, offset+length);
|
||||
}
|
||||
// Splits on a block boundary.
|
||||
int half = ((length + BLOCK_SIZE) >> 1) & BLOCK_MASK;
|
||||
return new CompositeNode(nodeOf(node, offset, half), nodeOf(node, offset + half, length - half));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the text representation of the <code>boolean</code> argument.
|
||||
*
|
||||
@@ -141,13 +155,15 @@ public final class ImmutableText extends ImmutableCharSequence implements CharAr
|
||||
|
||||
private static final ImmutableText FALSE = valueOf("false");
|
||||
|
||||
private static final ImmutableText EMPTY = valueOf("");
|
||||
private static final LeafNode EMPTY_NODE = new Leaf8BitNode(new byte[0]);
|
||||
private static final ImmutableText EMPTY = new ImmutableText(EMPTY_NODE);
|
||||
|
||||
/**
|
||||
* Returns the length of this text.
|
||||
*
|
||||
* @return the number of characters (16-bits Unicode) composing this text.
|
||||
*/
|
||||
@Override
|
||||
public int length() {
|
||||
return myNode.nodeLength();
|
||||
}
|
||||
@@ -162,7 +178,7 @@ public final class ImmutableText extends ImmutableCharSequence implements CharAr
|
||||
* @return <code>this + that</code>
|
||||
*/
|
||||
public ImmutableText concat(ImmutableText that) {
|
||||
return that.length() == 0 ? this : new ImmutableText(ensureChunked().myNode.concatNodes(that.ensureChunked().myNode));
|
||||
return that.length() == 0 ? this : new ImmutableText(concatNodes(ensureChunked().myNode, that.ensureChunked().myNode));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,28 +222,35 @@ public final class ImmutableText extends ImmutableCharSequence implements CharAr
|
||||
*/
|
||||
public ImmutableText delete(int start, int end) {
|
||||
if (start == end) return this;
|
||||
if (start > end)
|
||||
if (start > end) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
return ensureChunked().subtext(0, start).concat(subtext(end));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence subSequence(final int start, final int end) {
|
||||
if (start == 0 && end == length()) return this;
|
||||
return new CharSequenceSubSequence(this, start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
if (this == obj) {
|
||||
return true;
|
||||
if (!(obj instanceof ImmutableText))
|
||||
}
|
||||
if (!(obj instanceof ImmutableText)) {
|
||||
return false;
|
||||
final ImmutableText that = (ImmutableText) obj;
|
||||
}
|
||||
final ImmutableText that = (ImmutableText)obj;
|
||||
int len = this.length();
|
||||
if (len != that.length())
|
||||
if (len != that.length()) {
|
||||
return false;
|
||||
for (int i = 0; i < len;) {
|
||||
if (this.charAt(i) != that.charAt(i++))
|
||||
}
|
||||
for (int i = 0; i < len; ) {
|
||||
if (this.charAt(i) != that.charAt(i++)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -237,6 +260,7 @@ public final class ImmutableText extends ImmutableCharSequence implements CharAr
|
||||
*
|
||||
* @return the hash code value.
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = 0;
|
||||
final int length = this.length();
|
||||
@@ -246,16 +270,17 @@ public final class ImmutableText extends ImmutableCharSequence implements CharAr
|
||||
return h;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char charAt(int index) {
|
||||
if (myNode instanceof LeafNode) {
|
||||
return ((LeafNode)myNode)._data[index];
|
||||
return ((LeafNode)myNode).charAt(index);
|
||||
}
|
||||
|
||||
InnerLeaf leaf = myLastLeaf;
|
||||
if (leaf == null || index < leaf.offset || index >= leaf.offset + leaf.leafNode.nodeLength()) {
|
||||
myLastLeaf = leaf = findLeaf(index, 0);
|
||||
}
|
||||
return leaf.leafNode._data[index - leaf.offset];
|
||||
return leaf.leafNode.charAt(index - leaf.offset);
|
||||
}
|
||||
private volatile InnerLeaf myLastLeaf;
|
||||
|
||||
@@ -271,7 +296,8 @@ public final class ImmutableText extends ImmutableCharSequence implements CharAr
|
||||
CompositeNode composite = (CompositeNode)node;
|
||||
if (index < composite._head.nodeLength()) {
|
||||
node = composite._head;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
offset += composite._head.nodeLength();
|
||||
index -= composite._head.nodeLength();
|
||||
node = composite._tail;
|
||||
@@ -283,7 +309,7 @@ public final class ImmutableText extends ImmutableCharSequence implements CharAr
|
||||
final LeafNode leafNode;
|
||||
final int offset;
|
||||
|
||||
private InnerLeaf(LeafNode leafNode, int offset) {
|
||||
private InnerLeaf(@NotNull LeafNode leafNode, int offset) {
|
||||
this.leafNode = leafNode;
|
||||
this.offset = offset;
|
||||
}
|
||||
@@ -300,12 +326,15 @@ public final class ImmutableText extends ImmutableCharSequence implements CharAr
|
||||
* (start > end) || (end > this.length())</code>
|
||||
*/
|
||||
public ImmutableText subtext(int start, int end) {
|
||||
if ((start < 0) || (start > end) || (end > length()))
|
||||
if ((start < 0) || (start > end) || (end > length())) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
if ((start == 0) && (end == length()))
|
||||
}
|
||||
if ((start == 0) && (end == length())) {
|
||||
return this;
|
||||
if (start == end)
|
||||
}
|
||||
if (start == end) {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
return new ImmutableText(myNode.subNode(start, end));
|
||||
}
|
||||
@@ -321,6 +350,7 @@ public final class ImmutableText extends ImmutableCharSequence implements CharAr
|
||||
* @throws IndexOutOfBoundsException if <code>(start < 0) || (end < 0) ||
|
||||
* (start > end) || (end > this.length())</code>
|
||||
*/
|
||||
@Override
|
||||
public void getChars(int start, int end, @NotNull char[] dest, int destPos) {
|
||||
myNode.getChars(start, end, dest, destPos);
|
||||
}
|
||||
@@ -330,68 +360,69 @@ public final class ImmutableText extends ImmutableCharSequence implements CharAr
|
||||
*
|
||||
* @return the <code>java.lang.String</code> for this text.
|
||||
*/
|
||||
@Override
|
||||
@NotNull
|
||||
public String toString() {
|
||||
if (myNode instanceof LeafNode) { // Primitive.
|
||||
return new String(((LeafNode)myNode)._data, 0, length());
|
||||
} else { // Composite.
|
||||
int len = length();
|
||||
char[] data = new char[len];
|
||||
this.getChars(0, len, data, 0);
|
||||
return new String(data, 0, len);
|
||||
}
|
||||
return myNode.toString();
|
||||
}
|
||||
|
||||
private static abstract class Node {
|
||||
|
||||
private abstract static class Node {
|
||||
abstract int nodeLength();
|
||||
|
||||
Node concatNodes(Node that) {
|
||||
// All Text instances are maintained balanced:
|
||||
// (head < tail * 2) & (tail < head * 2)
|
||||
|
||||
final int length = this.nodeLength() + that.nodeLength();
|
||||
if (length <= BLOCK_SIZE) { // Merges to primitive.
|
||||
char[] chars = new char[length];
|
||||
this.getChars(0, this.nodeLength(), chars, 0);
|
||||
that.getChars(0, that.nodeLength(), chars, this.nodeLength());
|
||||
return new LeafNode(chars);
|
||||
} else { // Returns a composite.
|
||||
Node head = this;
|
||||
Node tail = that;
|
||||
|
||||
if (((head.nodeLength() << 1) < tail.nodeLength()) && tail instanceof CompositeNode) {
|
||||
// head too small, returns (head + tail/2) + (tail/2)
|
||||
if (((CompositeNode)tail)._head.nodeLength() > ((CompositeNode)tail)._tail.nodeLength()) {
|
||||
// Rotates to concatenate with smaller part.
|
||||
tail = ((CompositeNode)tail).rightRotation();
|
||||
}
|
||||
head = head.concatNodes(((CompositeNode)tail)._head);
|
||||
tail = ((CompositeNode)tail)._tail;
|
||||
|
||||
} else if (((tail.nodeLength() << 1) < head.nodeLength()) && head instanceof CompositeNode) {
|
||||
// tail too small, returns (head/2) + (head/2 concat tail)
|
||||
if (((CompositeNode)head)._tail.nodeLength() > ((CompositeNode)head)._head.nodeLength()) {
|
||||
// Rotates to concatenate with smaller part.
|
||||
head = ((CompositeNode)head).leftRotation();
|
||||
}
|
||||
tail = ((CompositeNode)head)._tail.concatNodes(tail);
|
||||
head = ((CompositeNode)head)._head;
|
||||
}
|
||||
return new CompositeNode(head, tail);
|
||||
}
|
||||
}
|
||||
|
||||
abstract void getChars(int start, int end, @NotNull char[] dest, int destPos);
|
||||
|
||||
abstract Node subNode(int start, int end);
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
int len = nodeLength();
|
||||
char[] data = new char[len];
|
||||
getChars(0, len, data, 0);
|
||||
return StringFactory.createShared(data);
|
||||
}
|
||||
}
|
||||
private abstract static class LeafNode extends Node {
|
||||
public abstract char charAt(int index);
|
||||
}
|
||||
|
||||
private static class LeafNode extends Node {
|
||||
final char[] _data;
|
||||
@NotNull
|
||||
private static Node concatNodes(@NotNull Node node1, @NotNull Node node2) {
|
||||
// All Text instances are maintained balanced:
|
||||
// (head < tail * 2) & (tail < head * 2)
|
||||
final int length = node1.nodeLength() + node2.nodeLength();
|
||||
if (length <= BLOCK_SIZE) { // Merges to primitive.
|
||||
char[] chars = new char[length];
|
||||
node1.getChars(0, node1.nodeLength(), chars, 0);
|
||||
node2.getChars(0, node2.nodeLength(), chars, node1.nodeLength());
|
||||
return createLeafNode(chars);
|
||||
}
|
||||
else { // Returns a composite.
|
||||
Node head = node1;
|
||||
Node tail = node2;
|
||||
|
||||
LeafNode(char[] _data) {
|
||||
if (((head.nodeLength() << 1) < tail.nodeLength()) && tail instanceof CompositeNode) {
|
||||
// head too small, returns (head + tail/2) + (tail/2)
|
||||
if (((CompositeNode)tail)._head.nodeLength() > ((CompositeNode)tail)._tail.nodeLength()) {
|
||||
// Rotates to concatenate with smaller part.
|
||||
tail = ((CompositeNode)tail).rightRotation();
|
||||
}
|
||||
head = concatNodes(head, ((CompositeNode)tail)._head);
|
||||
tail = ((CompositeNode)tail)._tail;
|
||||
}
|
||||
else if (((tail.nodeLength() << 1) < head.nodeLength()) && head instanceof CompositeNode) {
|
||||
// tail too small, returns (head/2) + (head/2 concat tail)
|
||||
if (((CompositeNode)head)._tail.nodeLength() > ((CompositeNode)head)._head.nodeLength()) {
|
||||
// Rotates to concatenate with smaller part.
|
||||
head = ((CompositeNode)head).leftRotation();
|
||||
}
|
||||
tail = concatNodes(((CompositeNode)head)._tail, tail);
|
||||
head = ((CompositeNode)head)._head;
|
||||
}
|
||||
return new CompositeNode(head, tail);
|
||||
}
|
||||
}
|
||||
|
||||
private static class WideLeafNode extends LeafNode {
|
||||
private final char[] _data;
|
||||
|
||||
WideLeafNode(@NotNull char[] _data) {
|
||||
this._data = _data;
|
||||
}
|
||||
|
||||
@@ -402,8 +433,9 @@ public final class ImmutableText extends ImmutableCharSequence implements CharAr
|
||||
|
||||
@Override
|
||||
void getChars(int start, int end, @NotNull char[] dest, int destPos) {
|
||||
if ((start < 0) || (end > nodeLength()) || (start > end))
|
||||
if ((start < 0) || (end > nodeLength()) || (start > end)) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
System.arraycopy(_data, start, dest, destPos, end - start);
|
||||
}
|
||||
|
||||
@@ -415,7 +447,56 @@ public final class ImmutableText extends ImmutableCharSequence implements CharAr
|
||||
int length = end - start;
|
||||
char[] chars = new char[length];
|
||||
System.arraycopy(_data, start, chars, 0, length);
|
||||
return new LeafNode(chars);
|
||||
return createLeafNode(chars);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return StringFactory.createShared(_data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public char charAt(int index) {
|
||||
return _data[index];
|
||||
}
|
||||
}
|
||||
|
||||
private static class Leaf8BitNode extends LeafNode {
|
||||
private final byte[] data;
|
||||
Leaf8BitNode(@NotNull byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
int nodeLength() {
|
||||
return data.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
void getChars(int start, int end, @NotNull char[] dest, int destPos) {
|
||||
if ((start < 0) || (end > nodeLength()) || (start > end)) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
for (int i=start;i<end;i++) {
|
||||
byte b = data[i];
|
||||
dest[destPos++] = (char)b;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
Node subNode(int start, int end) {
|
||||
if (start == 0 && end == nodeLength()) {
|
||||
return this;
|
||||
}
|
||||
int length = end - start;
|
||||
byte[] chars = new byte[length];
|
||||
System.arraycopy(data, start, chars, 0, length);
|
||||
return new Leaf8BitNode(chars);
|
||||
}
|
||||
|
||||
@Override
|
||||
public char charAt(int index) {
|
||||
return (char)data[index];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,8 +519,9 @@ public final class ImmutableText extends ImmutableCharSequence implements CharAr
|
||||
Node rightRotation() {
|
||||
// See: http://en.wikipedia.org/wiki/Tree_rotation
|
||||
Node P = this._head;
|
||||
if (!(P instanceof CompositeNode))
|
||||
if (!(P instanceof CompositeNode)) {
|
||||
return this; // Head not a composite, cannot rotate.
|
||||
}
|
||||
Node A = ((CompositeNode)P)._head;
|
||||
Node B = ((CompositeNode)P)._tail;
|
||||
Node C = this._tail;
|
||||
@@ -449,8 +531,9 @@ public final class ImmutableText extends ImmutableCharSequence implements CharAr
|
||||
Node leftRotation() {
|
||||
// See: http://en.wikipedia.org/wiki/Tree_rotation
|
||||
Node Q = this._tail;
|
||||
if (!(Q instanceof CompositeNode))
|
||||
if (!(Q instanceof CompositeNode)) {
|
||||
return this; // Tail not a composite, cannot rotate.
|
||||
}
|
||||
Node B = ((CompositeNode)Q)._head;
|
||||
Node C = ((CompositeNode)Q)._tail;
|
||||
Node A = this._head;
|
||||
@@ -462,9 +545,11 @@ public final class ImmutableText extends ImmutableCharSequence implements CharAr
|
||||
final int cesure = _head.nodeLength();
|
||||
if (end <= cesure) {
|
||||
_head.getChars(start, end, dest, destPos);
|
||||
} else if (start >= cesure) {
|
||||
}
|
||||
else if (start >= cesure) {
|
||||
_tail.getChars(start - cesure, end - cesure, dest, destPos);
|
||||
} else { // Overlaps head and tail.
|
||||
}
|
||||
else { // Overlaps head and tail.
|
||||
_head.getChars(start, cesure, dest, destPos);
|
||||
_tail.getChars(0, end - cesure, dest, destPos + cesure - start);
|
||||
}
|
||||
@@ -473,14 +558,17 @@ public final class ImmutableText extends ImmutableCharSequence implements CharAr
|
||||
@Override
|
||||
Node subNode(int start, int end) {
|
||||
final int cesure = _head.nodeLength();
|
||||
if (end <= cesure)
|
||||
if (end <= cesure) {
|
||||
return _head.subNode(start, end);
|
||||
if (start >= cesure)
|
||||
}
|
||||
if (start >= cesure) {
|
||||
return _tail.subNode(start - cesure, end - cesure);
|
||||
if ((start == 0) && (end == _count))
|
||||
}
|
||||
if ((start == 0) && (end == _count)) {
|
||||
return this;
|
||||
}
|
||||
// Overlaps head and tail.
|
||||
return _head.subNode(start, cesure).concatNodes(_tail.subNode(0, end - cesure));
|
||||
return concatNodes(_head.subNode(start, cesure), _tail.subNode(0, end - cesure));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,19 +72,18 @@ public class LineStatusTrackerDrawing {
|
||||
final EditorGutterComponentEx gutter = ((EditorEx)editor).getGutterComponentEx();
|
||||
Color stripeColor = getDiffGutterColor(range);
|
||||
|
||||
boolean foldingOutlineShown = ((EditorEx)editor).getGutterComponentEx().isFoldingOutlineShown();
|
||||
int triangle = 4;
|
||||
if (range.getInnerRanges() == null) { // actual painter
|
||||
g.setColor(stripeColor);
|
||||
|
||||
final int endX = gutter.getWhitespaceSeparatorOffset();
|
||||
final int x = r.x + r.width - 4;
|
||||
final int x = r.x + r.width - 3;
|
||||
final int width = endX - x;
|
||||
if (r.height > 0) {
|
||||
g.fillRect(x, r.y, width, r.height); // todo: intersection with dotted gutter outline
|
||||
g.fillRect(x, r.y, width, r.height);
|
||||
}
|
||||
else {
|
||||
final int[] xPoints = new int[]{x, x, endX - (foldingOutlineShown ? -1 : triangle + 1)};
|
||||
final int[] xPoints = new int[]{x, x, endX};
|
||||
final int[] yPoints = new int[]{r.y - triangle, r.y + triangle, r.y};
|
||||
g.fillPolygon(xPoints, yPoints, 3);
|
||||
}
|
||||
@@ -97,7 +96,7 @@ public class LineStatusTrackerDrawing {
|
||||
if (range.getType() == Range.DELETED) {
|
||||
final int y = lineToY(editor, range.getLine1());
|
||||
|
||||
final int[] xPoints = new int[]{x, x, endX - (foldingOutlineShown ? 0 : triangle + 1)};
|
||||
final int[] xPoints = new int[]{x, x, endX + 1};
|
||||
final int[] yPoints = new int[]{y - triangle, y + triangle, y};
|
||||
|
||||
g.setColor(stripeColor);
|
||||
@@ -215,7 +214,7 @@ public class LineStatusTrackerDrawing {
|
||||
toolbar.setBackground(background);
|
||||
|
||||
toolbar
|
||||
.setBorder(new ColoredSideBorder(foreground, foreground, (range.getType() != Range.INSERTED) ? null : foreground, foreground, 1));
|
||||
.setBorder(new ColoredSideBorder(foreground, foreground, range.getType() != Range.INSERTED ? null : foreground, foreground, 1));
|
||||
|
||||
final JPanel component = new JPanel(new BorderLayout());
|
||||
component.setOpaque(false);
|
||||
|
||||
@@ -16,31 +16,24 @@
|
||||
package org.zmlx.hg4idea.push;
|
||||
|
||||
import com.intellij.dvcs.push.VcsPushOptionsPanel;
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import com.intellij.ui.components.JBCheckBox;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class HgPushOptionsPanel extends VcsPushOptionsPanel {
|
||||
|
||||
private final ComboBox myReferenceStrategyCombobox;
|
||||
private final JBCheckBox myPushBookmarkCheckBox;
|
||||
|
||||
public HgPushOptionsPanel() {
|
||||
setLayout(new BorderLayout());
|
||||
myReferenceStrategyCombobox = new ComboBox();
|
||||
HgVcsPushOptionValue[] values = HgVcsPushOptionValue.values();
|
||||
DefaultComboBoxModel comboModel = new DefaultComboBoxModel(values);
|
||||
myReferenceStrategyCombobox.setModel(comboModel);
|
||||
JLabel referenceStrategyLabel = new JLabel("Export Bookmarks: ");
|
||||
add(referenceStrategyLabel, BorderLayout.WEST);
|
||||
add(myReferenceStrategyCombobox, BorderLayout.CENTER);
|
||||
myPushBookmarkCheckBox = new JBCheckBox("Export Active Bookmarks");
|
||||
add(myPushBookmarkCheckBox, BorderLayout.WEST);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
@Nullable
|
||||
public HgVcsPushOptionValue getValue() {
|
||||
return (HgVcsPushOptionValue)myReferenceStrategyCombobox.getSelectedItem();
|
||||
return myPushBookmarkCheckBox.isSelected() ? HgVcsPushOptionValue.Current : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -217,14 +217,14 @@ public class StudyTaskManager implements ProjectComponent, PersistentStateCompon
|
||||
}
|
||||
});
|
||||
}
|
||||
addShortcut(StudyNextWindowAction.SHORTCUT, StudyNextWindowAction.ACTION_ID);
|
||||
addShortcut(StudyPrevWindowAction.SHORTCUT, StudyPrevWindowAction.ACTION_ID);
|
||||
addShortcut(StudyShowHintAction.SHORTCUT, StudyShowHintAction.ACTION_ID);
|
||||
addShortcut(StudyNextWindowAction.SHORTCUT2, StudyNextWindowAction.ACTION_ID);
|
||||
addShortcut(StudyCheckAction.SHORTCUT, StudyCheckAction.ACTION_ID);
|
||||
addShortcut(StudyNextStudyTaskAction.SHORTCUT, StudyNextStudyTaskAction.ACTION_ID);
|
||||
addShortcut(StudyPreviousStudyTaskAction.SHORTCUT, StudyPreviousStudyTaskAction.ACTION_ID);
|
||||
addShortcut(StudyRefreshTaskFileAction.SHORTCUT, StudyRefreshTaskFileAction.ACTION_ID);
|
||||
addShortcut(StudyNextWindowAction.SHORTCUT, StudyNextWindowAction.ACTION_ID, false);
|
||||
addShortcut(StudyPrevWindowAction.SHORTCUT, StudyPrevWindowAction.ACTION_ID, false);
|
||||
addShortcut(StudyShowHintAction.SHORTCUT, StudyShowHintAction.ACTION_ID, false);
|
||||
addShortcut(StudyNextWindowAction.SHORTCUT2, StudyNextWindowAction.ACTION_ID, true);
|
||||
addShortcut(StudyCheckAction.SHORTCUT, StudyCheckAction.ACTION_ID, false);
|
||||
addShortcut(StudyNextStudyTaskAction.SHORTCUT, StudyNextStudyTaskAction.ACTION_ID, false);
|
||||
addShortcut(StudyPreviousStudyTaskAction.SHORTCUT, StudyPreviousStudyTaskAction.ACTION_ID, false);
|
||||
addShortcut(StudyRefreshTaskFileAction.SHORTCUT, StudyRefreshTaskFileAction.ACTION_ID, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -233,10 +233,10 @@ public class StudyTaskManager implements ProjectComponent, PersistentStateCompon
|
||||
}
|
||||
|
||||
|
||||
private static void addShortcut(@NotNull final String shortcutString, @NotNull final String actionIdString) {
|
||||
private static void addShortcut(@NotNull final String shortcutString, @NotNull final String actionIdString, boolean isAdditional) {
|
||||
Keymap keymap = KeymapManager.getInstance().getActiveKeymap();
|
||||
Shortcut[] shortcuts = keymap.getShortcuts(actionIdString);
|
||||
if (shortcuts.length > 0) {
|
||||
if (shortcuts.length > 0 && !isAdditional) {
|
||||
return;
|
||||
}
|
||||
Shortcut studyActionShortcut = new KeyboardShortcut(KeyStroke.getKeyStroke(shortcutString), null);
|
||||
|
||||
+1
-2
@@ -33,8 +33,7 @@ public class PythonRegexpParserDefinition extends RegExpParserDefinition {
|
||||
public static final IFileElementType PYTHON_REGEXP_FILE = new IFileElementType("PYTHON_REGEXP_FILE", PythonRegexpLanguage.INSTANCE);
|
||||
protected final EnumSet<RegExpCapability> CAPABILITIES = EnumSet.of(RegExpCapability.DANGLING_METACHARACTERS,
|
||||
RegExpCapability.OCTAL_NO_LEADING_ZERO,
|
||||
RegExpCapability.OMIT_NUMBERS_IN_QUANTIFIERS,
|
||||
RegExpCapability.ALLOW_EMPTY_CHARACTER_CLASS);
|
||||
RegExpCapability.OMIT_NUMBERS_IN_QUANTIFIERS);
|
||||
|
||||
@NotNull
|
||||
public Lexer createLexer(Project project) {
|
||||
|
||||
@@ -25,9 +25,9 @@ import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.TextEditor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiComment;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.inspections.PyEncodingUtil;
|
||||
import com.jetbrains.python.psi.LanguageLevel;
|
||||
@@ -71,20 +71,20 @@ public class AddEncodingQuickFix implements LocalQuickFix {
|
||||
if (firstLine instanceof PsiComment && firstLine.getText().startsWith("#!")) {
|
||||
firstLine = firstLine.getNextSibling();
|
||||
}
|
||||
final LanguageLevel languageLevel = LanguageLevel.forElement(file);
|
||||
final String commentText = String.format(PyEncodingUtil.ENCODING_FORMAT_PATTERN[myEncodingFormatIndex], myDefaultEncoding);
|
||||
final PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
|
||||
PsiComment encodingComment = elementGenerator.createFromText(LanguageLevel.forElement(file), PsiComment.class, commentText);
|
||||
PsiComment encodingComment = elementGenerator.createFromText(languageLevel, PsiComment.class, commentText);
|
||||
encodingComment = (PsiComment)file.addBefore(encodingComment, firstLine);
|
||||
|
||||
final FileEditor fileEditor = FileEditorManager.getInstance(project).getSelectedEditor(element.getContainingFile().getVirtualFile());
|
||||
if (fileEditor instanceof TextEditor) {
|
||||
if (encodingComment.getNextSibling() == null || !encodingComment.getNextSibling().textContains('\n')) {
|
||||
file.addAfter(elementGenerator.createFromText(languageLevel, PsiWhiteSpace.class, "\n"), encodingComment);
|
||||
}
|
||||
final Editor editor = ((TextEditor)fileEditor).getEditor();
|
||||
final Document document = editor.getDocument();
|
||||
final int insertedLineNumber = document.getLineNumber(encodingComment.getTextOffset());
|
||||
if (insertedLineNumber == document.getLineCount() - 1) {
|
||||
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document);
|
||||
document.insertString(document.getLineEndOffset(insertedLineNumber), "\n");
|
||||
}
|
||||
editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(insertedLineNumber + 1, 0));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
<warning descr="No encoding specified for file"><caret></warning>
|
||||
<warning descr="No encoding specified for file"><caret></warning>#!/usr/bin/env python
|
||||
+1
@@ -1,2 +1,3 @@
|
||||
#!/usr/bin/env python
|
||||
# coding=utf-8
|
||||
<caret>
|
||||
@@ -356,8 +356,8 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
}
|
||||
|
||||
// PY-13297
|
||||
public void testAddEncodingInEmptyFile() {
|
||||
doInspectionTest("AddEncodingInEmptyFile.py", PyMandatoryEncodingInspection.class,
|
||||
public void testAddEncodingAtLastLine() {
|
||||
doInspectionTest("AddEncodingAtLastLine.py", PyMandatoryEncodingInspection.class,
|
||||
PyBundle.message("QFIX.add.encoding"), true, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.xml.XmlFile;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
@@ -41,7 +42,10 @@ public class EnterBetweenXmlTagsHandler extends EnterHandlerDelegateAdapter {
|
||||
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
|
||||
|
||||
if (file instanceof XmlFile && isBetweenXmlTags(project, editor, file, caretOffset.get().intValue())) {
|
||||
originalHandler.execute(editor, dataContext);
|
||||
editor.getDocument().insertString(caretOffset.get(), "\n");
|
||||
if (project != null) {
|
||||
CodeStyleManager.getInstance(project).adjustLineIndent(editor.getDocument(), caretOffset.get() + 1);
|
||||
}
|
||||
return Result.DefaultForceIndent;
|
||||
}
|
||||
return Result.Continue;
|
||||
|
||||
@@ -89,13 +89,13 @@ public class EmmetPreviewHint extends LightweightHint implements Disposable {
|
||||
JRootPane pane = myParentEditor.getComponent().getRootPane();
|
||||
JComponent layeredPane = pane != null ? pane.getLayeredPane() : myParentEditor.getComponent();
|
||||
HintHint hintHint = new HintHint(layeredPane, position.first)
|
||||
.setAwtTooltip(true)
|
||||
.setContentActive(true)
|
||||
.setExplicitClose(true)
|
||||
.setShowImmediately(true)
|
||||
.setPreferredPosition(position.second == HintManager.ABOVE ? Balloon.Position.above : Balloon.Position.below)
|
||||
.setTextBg(myParentEditor.getColorsScheme().getDefaultBackground())
|
||||
.setBorderInsets(new Insets(1, 1, 1, 1));
|
||||
.setAwtTooltip(true)
|
||||
.setContentActive(true)
|
||||
.setExplicitClose(true)
|
||||
.setShowImmediately(true)
|
||||
.setPreferredPosition(position.second == HintManager.ABOVE ? Balloon.Position.above : Balloon.Position.below)
|
||||
.setTextBg(myParentEditor.getColorsScheme().getDefaultBackground())
|
||||
.setBorderInsets(new Insets(1, 1, 1, 1));
|
||||
|
||||
int hintFlags = HintManager.HIDE_BY_OTHER_HINT | HintManager.HIDE_BY_ESCAPE | HintManager.UPDATE_BY_SCROLLING;
|
||||
HintManagerImpl.getInstanceImpl().showEditorHint(this, myParentEditor, position.first, hintFlags, 0, false, hintHint);
|
||||
@@ -123,7 +123,7 @@ public class EmmetPreviewHint extends LightweightHint implements Disposable {
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
|
||||
@TestOnly
|
||||
@NotNull
|
||||
public String getContent() {
|
||||
@@ -143,7 +143,9 @@ public class EmmetPreviewHint extends LightweightHint implements Disposable {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static EmmetPreviewHint createHint(@NotNull final EditorEx parentEditor, @NotNull String templateText, @NotNull FileType fileType) {
|
||||
public static EmmetPreviewHint createHint(@NotNull final EditorEx parentEditor,
|
||||
@NotNull String templateText,
|
||||
@NotNull FileType fileType) {
|
||||
EditorFactory editorFactory = EditorFactory.getInstance();
|
||||
Document document = editorFactory.createDocument(templateText);
|
||||
final EditorEx previewEditor = (EditorEx)editorFactory.createEditor(document, parentEditor.getProject(), fileType, true);
|
||||
@@ -172,9 +174,9 @@ public class EmmetPreviewHint extends LightweightHint implements Disposable {
|
||||
Dimension parentEditorSize = parentEditor.getScrollPane().getSize();
|
||||
int maxWidth = (int)parentEditorSize.getWidth() / 3;
|
||||
int maxHeight = (int)parentEditorSize.getHeight() / 2;
|
||||
Dimension contentSize = previewEditor.getContentSize();
|
||||
return new Dimension(maxWidth > contentSize.getWidth() && !settings.isUseSoftWraps() ? (int)size.getWidth() : maxWidth,
|
||||
maxHeight > contentSize.getHeight() ? (int)size.getHeight() : maxHeight);
|
||||
final int width = settings.isUseSoftWraps() ? maxWidth : Math.min((int)size.getWidth(), maxWidth);
|
||||
final int height = Math.min((int)size.getHeight(), maxHeight);
|
||||
return new Dimension(width, height);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -105,6 +105,20 @@ public class XmlTypedHandlersTest extends LightPlatformCodeInsightFixtureTestCas
|
||||
"</foo>");
|
||||
}
|
||||
|
||||
public void testWeb13982() throws Exception {
|
||||
doTest(
|
||||
"<a foo=\"1\"\n" +
|
||||
" bar=\"2\"><caret></a>",
|
||||
|
||||
'\n',
|
||||
|
||||
"<a foo=\"1\"\n" +
|
||||
" bar=\"2\">\n" +
|
||||
" <caret>\n" +
|
||||
"</a>"
|
||||
);
|
||||
}
|
||||
|
||||
private void doTest(String text, char c, String result) {
|
||||
myFixture.configureByText(XmlFileType.INSTANCE, text);
|
||||
myFixture.type(c);
|
||||
|
||||
@@ -59,7 +59,7 @@ public class CheckTagEmptyBodyInspection extends XmlSuppressableInspectionTool {
|
||||
|
||||
if (node != null &&
|
||||
node.getElementType() == XmlTokenType.XML_END_TAG_START) {
|
||||
final LocalQuickFix localQuickFix = new ReplaceEmptyTagBodyByEmptyEndFix();
|
||||
final LocalQuickFix localQuickFix = new Fix();
|
||||
holder.registerProblem(
|
||||
tag,
|
||||
XmlBundle.message("xml.inspections.tag.empty.body"),
|
||||
@@ -98,7 +98,7 @@ public class CheckTagEmptyBodyInspection extends XmlSuppressableInspectionTool {
|
||||
return "CheckTagEmptyBody";
|
||||
}
|
||||
|
||||
private static class ReplaceEmptyTagBodyByEmptyEndFix implements LocalQuickFix {
|
||||
public static class Fix implements LocalQuickFix {
|
||||
@Override
|
||||
@NotNull
|
||||
public String getName() {
|
||||
|
||||
@@ -35,7 +35,9 @@ public abstract class XmlSuppressableInspectionTool extends LocalInspectionTool
|
||||
|
||||
@NotNull
|
||||
public static SuppressQuickFix[] getSuppressFixes(@NotNull String shortName, @NotNull XmlSuppressionProvider provider) {
|
||||
final String id = HighlightDisplayKey.find(shortName).getID();
|
||||
HighlightDisplayKey key = HighlightDisplayKey.find(shortName);
|
||||
if (key == null) return SuppressQuickFix.EMPTY_ARRAY;
|
||||
final String id = key.getID();
|
||||
return new SuppressQuickFix[]{new SuppressTagStatic(id, provider), new SuppressForFile(id, provider), new SuppressAllForFile(provider)};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user