eclipse的JDT的hover是如何显示出来的

1.什么是JDT的hover。

见下图:

2. hover中的不同的字体,和颜色是如何显示出来的。

其实在对应的hover中,返回的是String类型,内容是html,然后通过org.eclipse.swt.browser.Browser显示出来的。

3.工作原理:

3.1 add MouseTracker to current SourceViewer, when you open java file.
org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor$AdaptedSourceViewer
-->
org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor$AdaptedSourceViewer

/**
 * After this method has been executed the caller knows that any installed text hover has been installed.
 */
private void ensureHoverControlManagerInstalled() {
    if (fTextHovers != null && !fTextHovers.isEmpty() && fHoverControlCreator != null && fTextHoverManager == null) {
        fTextHoverManager= new TextViewerHoverManager(this, fHoverControlCreator);
        fTextHoverManager.install(this.getTextWidget());
        fTextHoverManager.setSizeConstraints(TEXT_HOVER_WIDTH_CHARS, TEXT_HOVER_HEIGHT_CHARS, false, true);
        fTextHoverManager.setInformationControlReplacer(new StickyHoverManager(this));
    }
}

--> org.eclipse.jface.text.TextViewerHoverManager

public void install(Control subjectControl) {
    if (fSubjectControl != null && !fSubjectControl.isDisposed() && fSubjectControlDisposeListener != null)
        fSubjectControl.removeDisposeListener(fSubjectControlDisposeListener);

    fSubjectControl= subjectControl;

    if (fSubjectControl != null)
        fSubjectControl.addDisposeListener(getSubjectControlDisposeListener());

    if (fInformationControlCloser != null)
        fInformationControlCloser.setSubjectControl(subjectControl);

    setEnabled(true);
    fDisposed= false;
}

--> org.eclipse.jface.text.TextViewerHoverManager

public void setEnabled(boolean enabled) {

    boolean was= isEnabled();
    super.setEnabled(enabled);
    boolean is= isEnabled();

    if (was != is && fMouseTracker != null) {
        if (is)
            fMouseTracker.start(getSubjectControl());
        else
            fMouseTracker.stop();
    }
}

-->
org.eclipse.jface.text.AbstractHoverInformationControlManager$MouseTracker

public void start(Control subjectControl) {
    fSubjectControl= subjectControl;
    if (fSubjectControl != null && !fSubjectControl.isDisposed())
        fSubjectControl.addMouseTrackListener(this);

    fIsInRestartMode= false;
    fIsComputing= false;
    fMouseLostWhileComputing= false;
    fShellDeactivatedWhileComputing= false;
}

3.2 when you hover mouse on target SourceViewer, it will show hover
org.eclipse.jface.text.AbstractHoverInformationControlManager$MouseTracker

public void mouseHover(MouseEvent event) {
    if (fIsComputing || fIsInRestartMode ||
            (fSubjectControl != null && !fSubjectControl.isDisposed() && fSubjectControl.getShell() != fSubjectControl.getShell().getDisplay().getActiveShell())) {
        if (DEBUG)
            System.out.println("AbstractHoverInformationControlManager...mouseHover: @ " + event.x + "/" + event.y + " : hover cancelled: fIsComputing= " + fIsComputing + ", fIsInRestartMode= " + fIsInRestartMode); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
        return;
    }

    fIsInRestartMode= true;
    fIsComputing= true;
    fMouseLostWhileComputing= false;
    fShellDeactivatedWhileComputing= false;

    fHoverEventStateMask= event.stateMask;
    fHoverEvent= event;
    fHoverArea= new Rectangle(event.x - EPSILON, event.y - EPSILON, 2 * EPSILON, 2 * EPSILON );
    if (fHoverArea.x < 0)
        fHoverArea.x= 0;
    if (fHoverArea.y < 0)
        fHoverArea.y= 0;
    setSubjectArea(fHoverArea);

    if (fSubjectControl != null && !fSubjectControl.isDisposed()) {
        fSubjectControl.addMouseMoveListener(this);
        fSubjectControl.getShell().addShellListener(this);
    }
    doShowInformation();
}

--> org.eclipse.jface.text.AbstractInformationControlManager

protected void doShowInformation() {
    fSubjectArea= null;
    fInformation= null;
    computeInformation();
}

--> org.eclipse.jface.text.TextViewerHoverManager

protected void computeInformation() {
//create a thread(Text Viewer Hover Presenter) to show hover
}


-->
org.eclipse.jface.text.AbstractInformationControlManager.internalShowInformationControl(Rectangle,
Object) to create control to show the text.

private void internalShowInformationControl(Rectangle subjectArea, Object information) {
    if (this instanceof InformationControlReplacer) {
        ((InformationControlReplacer) this).showInformationControl(subjectArea, information);
        return;
    }

    IInformationControl informationControl= getInformationControl();
    if (informationControl != null) {

        Point sizeConstraints= computeSizeConstraints(fSubjectControl, fSubjectArea, informationControl);
        if (informationControl instanceof IInformationControlExtension3) {
            IInformationControlExtension3 iControl3= (IInformationControlExtension3) informationControl;
            Rectangle trim= iControl3.computeTrim();
            sizeConstraints.x += trim.width;
            sizeConstraints.y += trim.height;
        }
        informationControl.setSizeConstraints(sizeConstraints.x, sizeConstraints.y);

        if (informationControl instanceof IInformationControlExtension2)
            ((IInformationControlExtension2)informationControl).setInput(information);
        else
            informationControl.setInformation(information.toString());

        if (informationControl instanceof IInformationControlExtension) {
            IInformationControlExtension extension= (IInformationControlExtension)informationControl;
            if (!extension.hasContents())
                return;
        }

        Point size= null;
        Point location= null;
        Rectangle bounds= restoreInformationControlBounds();

        if (bounds != null) {
            if (bounds.x > -1 && bounds.y > -1)
                location= Geometry.getLocation(bounds);

            if (bounds.width > -1 && bounds.height > -1)
                size= Geometry.getSize(bounds);
        }

        if (size == null)
            size= informationControl.computeSizeHint();

        if (fEnforceAsMinimalSize)
            size= Geometry.max(size, sizeConstraints);
        if (fEnforceAsMaximalSize)
            size= Geometry.min(size, sizeConstraints);

        if (location == null)
            location= computeInformationControlLocation(subjectArea, size);

        Rectangle controlBounds= Geometry.createRectangle(location, size);
        cropToClosestMonitor(controlBounds);
        location= Geometry.getLocation(controlBounds);
        size= Geometry.getSize(controlBounds);
        informationControl.setLocation(location);
        informationControl.setSize(size.x, size.y);

        showInformationControl(subjectArea);
    }
}

--> org.eclipse.jface.text.AbstractInformationControlManager

protected void showInformationControl(Rectangle subjectArea) {
    fInformationControl.setVisible(true);

    if (fInformationControl == null)
        return; // could already be disposed if setVisible(..) runs the display loop

    if (fTakesFocusWhenVisible)
        fInformationControl.setFocus();

    if (fInformationControlCloser != null)
        fInformationControlCloser.start(subjectArea);
}

org.eclipse.jdt.internal.ui.text.java.hover.JavadocHover$HoverControlCreator

public IInformationControl doCreateInformationControl(Shell parent) {
        String tooltipAffordanceString= fAdditionalInfoAffordance ? JavaPlugin.getAdditionalInfoAffordanceString() : EditorsUI.getTooltipAffordanceString();
        if (BrowserInformationControl.isAvailable(parent)) {
            String font= PreferenceConstants.APPEARANCE_JAVADOC_FONT;
            BrowserInformationControl iControl= new BrowserInformationControl(parent, font, tooltipAffordanceString) {
                /*
                 * @see org.eclipse.jface.text.IInformationControlExtension5#getInformationPresenterControlCreator()
                 */
                @Override
                public IInformationControlCreator getInformationPresenterControlCreator() {
                    return fInformationPresenterControlCreator;
                }
            };
            addLinkListener(iControl);
            return iControl;
        } else {
            return new DefaultInformationControl(parent, tooltipAffordanceString);
        }
    }

4. 下面是System.out.println的html内容和在firefox下显示的效果。

<html><head><style CHARSET="ISO-8859-1" TYPE="text/css">/* Font definitions */
html         { font-family: 'Sans',sans-serif; font-size: 10pt; font-style: normal; font-weight: normal; }
body, h1, h2, h3, h4, h5, h6, p, table, td, caption, th, ul, ol, dl, li, dd, dt { font-size: 1em; }
pre          { font-family: monospace; }

/* Margins */
body         { overflow: auto; margin-top: 0px; margin-bottom: 0.5em; margin-left: 0.3em; margin-right: 0px; }
h1           { margin-top: 0.3em; margin-bottom: 0.04em; }    
h2           { margin-top: 2em; margin-bottom: 0.25em; }
h3           { margin-top: 1.7em; margin-bottom: 0.25em; }
h4           { margin-top: 2em; margin-bottom: 0.3em; }
h5           { margin-top: 0px; margin-bottom: 0px; }
p            { margin-top: 1em; margin-bottom: 1em; }
pre          { margin-left: 0.6em; }
ul             { margin-top: 0px; margin-bottom: 1em; margin-left: 1em; padding-left: 1em;}
li             { margin-top: 0px; margin-bottom: 0px; } 
li p         { margin-top: 0px; margin-bottom: 0px; } 
ol             { margin-top: 0px; margin-bottom: 1em; margin-left: 1em; padding-left: 1em; }
dl             { margin-top: 0px; margin-bottom: 1em; }
dt             { margin-top: 0px; margin-bottom: 0px; font-weight: bold; }
dd             { margin-top: 0px; margin-bottom: 0px; }

/* Styles and colors */
a:link         { color: #0000FF; }
a:hover         { color: #000080; }
a:visited    { text-decoration: underline; }
a.header:link    { text-decoration: none; color: #000000 }
a.header:visited { text-decoration: none; color: #000000 }
a.header:hover   { text-decoration: underline; color: #000080; }
h4           { font-style: italic; }
strong         { font-weight: bold; }
em             { font-style: italic; }
var             { font-style: italic; }
th             { font-weight: bold; }

/* Workarounds for new Javadoc stylesheet (1.7) */ 
ul.blockList li.blockList, ul.blockListLast li.blockList {
    list-style:none;
}
ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast {
    list-style:none;
}
</style>
<base href='http://download.oracle.com/javase/7/docs/api/java/io/PrintStream.html'>
</head><body style="overflow:hidden;" text="#000000" bgcolor="#ffffbf"><h5><div style='word-wrap: break-word; position: relative; margin-left: 20px; padding-top: 2px; '><a href=''><!--[if lte IE 6]><![if gte IE 5.5]>
<span alt='Open Declaration' style="border:none; position: absolute; width: 16px; height: 16px; left: -21px; filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='')"></span>
<![endif]><![endif]-->
<!--[if !IE]>-->
<img alt='Open Declaration' style='border:none; position: absolute; width: 16px; height: 16px; left: -21px; ' src='/>
<!--<![endif]-->
<!--[if gte IE 7]>
<img alt='Open Declaration' style='border:none; position: absolute; width: 16px; height: 16px; left: -21px; ' src='file:'/>
<![endif]-->
</a>void <a class='header' href=''>java</a>.<a class='header' href=''>io</a>.<a class='header' href=''>PrintStream</a>.println(<span style='font-weight:normal;'></span>int x)</div></h5><br><p>Prints an integer and then terminate the line.  This method behaves as
 though it invokes <code><code><a href=''>print(int)</a></code></code> and then
 <code><code><a href=''>println()</a></code></code>.<dl><dt>Parameters:</dt><dd><b>x</b>   The <code>int</code> to be printed.</dd></dl></body></html>

显示效果:

以逗号分割,但是不包含括号内的逗号的正则表达式

首先正则表达式是:

,(?![^()]*+\))

stackoverflow.com/questions/628583/regular-expression-to-split-on-commas-
not-enclosed-in-parenthesis

接下来我们来显示解释:

,表示匹配逗号

*[^()] 表示除过左括号和右括号的所有字符重复零次或多次; **

*![^()]+\) 表示 除过左括号和右括号的所有字符重复零次或多次 ,然后最后一个字符是右括号 1)
**

如下图:

**,(?![^()]*+\)) 表示逗号之后不能是 1)pattern所匹配的字符串。

**如下图,我们用它类分割1,23,test,(1,2,3):

**


**注意,这个正则表达式不支持括号的嵌套

正则表达式中的look-around

使用向前看和上后看你可以来完成各种各样的assert来满足你的需求。
在字符串处理时,你可以向前或者向后看,同时你可以让你所看的pattern是成功或者失败。
就像Java中的assert()

(?=pattern)
is a positive look-ahead assertion
assert(pattern match) –>

(?!pattern)
is a negative look-ahead assertion
assert(pattern not match) –>

(?<=pattern)
is a positive look-behind assertion
assert(pattern match) <--

(?<!pattern)
is a negative look-behind assertion
assert(pattern not match) <--

look-ahead –>向前看
look-behind <--向后看

1. 寻找最后出现的字符串
这里有很多不使用左右看的方法来完成寻找最后出现的字符串,
但是如果你需要的是:最后的字符串是foo并且foo之后再也没有foo字符串了(可以有其它的字符串),你可以使用:

/foo(?!.*foo)/

正则表达式引擎会在找到foo之后使用look-around中的pattern .*foo去匹配,如果匹配到,但是因为是getative的,
所有assert失败,然后正则表达式引擎会继续查找下一个foo。

例如:foobar会匹配到第一个foo

而foobarfooeee会匹配到第二个foo

以(?<=foo)作为分隔符

2. 替换之前,之后或者中间的字符
Many substitutions match a chunk of text and then replace part or all of it.
You can often avoid that by using look-arounds.
For example, if you want to put a comma after every foo:
很多替换方法匹配一串字符的全部或者一部分。你可以使用look-around来实现。
例如,你想要在每个foo之后都加一个逗号:

s/(?<=foo)/,/g; # 不使用向后看: s/foo/foo,/g or s/(foo)/$1,/g

或者给lookahead中间加一个-

s/(?<=look)(?=ahead)/-/g;

需要注意的是,左右看这种方法不能有变量长度,这意味着你不能在它之后或者之内使用像(?, *, +, or {1,5}) 这样的限定符。

将lookahead替换成look-ahead

3. 匹配一个pattern但是不包含其它的pattern
You might want to capture everything between foo and bar that doesn’t include
baz.
The technique is to have the regex engine look-ahead at every character to
ensure
that it isn’t the beginning of the undesired pattern:
你可能想匹配所有在foo和bar之间的字符串,但是foo之后不能是baz。
你可以使用下面的表达式:

/foo # Match starting at foo
( # Capture
(?: # Complex expression(you do not use the backreference):
(?!baz) # make sure we’re not at the beginning of baz

#or using (?!.baz) make sure the whole string between foo and bar not
contains baz
. # accept any character
)
# any number of times
) # End capture
bar # and ending at bar
/x;

foo((?:(?!baz).*))bar

不会匹配foobazddbar

foo之后不知baz,所以匹配上了

如果想匹配foo和bar之间没有baz可以使用:

foo((?:(?!.baz).))bar

4. 嵌套
look-arounds是可以嵌套的。look-arounds的自表达式会冲它上层继承开始位置,然后在这个开始位置的基础上
左右看同时不影响上层的位置,子表达式和父亲是相互独立的,它们独自维护自己的位置信息。

这个概念很简单,但是表达式很快就会变的很难懂。所有推荐对正则表达式加注释。
下面让我们来看一个正则表达式的例子。我们希望在任何分隔符(为了简单我们只用,)之后加一个空格,
但是在两个数字之间的,不加空格。

s/(?<=, # after a comma,
(?! # but not matching
(?<=\d,) # digit-comma before, AND
(?=\d) # digit afterward
)
)/ /gx; # substitute a space

(?<=,(?!(?<=\d,)(?=\d)))

在,之后加空格,但是数字之间的不加

注意,我们可以使用多个lookaround来完成不同的条件。就像And或这Or。
事实上你可是使用布尔代数表达式 ( NOT (a AND b) === (NOT a OR NOT b) )
来转化上面的表达式

s/(?<=, # after a comma, but either
(?:
(?<!\d,) # not matching digit-comma before
| # OR
(?!\d) # not matching digit afterward
)
)/ /gx; # substitute a space

(?<=,(?:(?<!\d,)|(?!\d)))

4. 捕获
有时我们会在look-around中捕获大括号。你可能认为你不会用到。
但是还是请你记住: the capturing parentheses must be within the look-around expression。
从enclosing expression来看,lookaround其实没有进行匹配。

最有用的技巧是在全局匹配模式时寻找重叠的匹配。
你可以捕获子串但是不需要消耗它,然后它可以对后面的匹配有效。
或许最简单的例子就是获得所有的右边的子串

print “$1\n” while /(?=(.*))/g;

注意这个模式理论上不会消耗任何一个字符,但是Perl在空匹配时会自动追加一个字符来防止无限循环。
http://www.perlmonks.org/?node_id=518444

vi中的分屏命令

:sp 画面上下分割
:sp filename 在分割的画面中打开文件
Ctrl-w p 画面间移动
Ctrl-w k 上画面移动
Ctrl-w j 下画面移动
Ctrl-w l 右画面移动
Ctrl-w h 左画面移动

Ctrl-w Ctrl-w == Ctrl-w p
Ctrl-w q == :q 关闭当前画面
Ctrl-w v == :vsp
Ctrl-w s == :sp

突然掉电后,clearcase总是提示I/O error

1. 首先重新启动一下机器,确保和clearcase server之间的链接正常

2. 重启本机的clearcase client

Stops Rational ClearCase.

ccase-home-dir/etc/clearcase stop

Starts Rational ClearCase.

ccase-home-dir/etc/clearcase start

3. 检查clearcase的log

ClearCase log directory:
/var/adm/rational/clearcase/log

在这个目录下面grep以下最近的时间,一般会找出出错的提示,然后google,就可以了。
比如我的log中总是提示format不对,然后google,使用下面的命令就可以了。
ct reformatview -tag view_tag

Java中sleep和wait的区别

1. wait, notify, notifyAll等方法是Object的,而sleep, join, yield等方法是Thread的;

2. wait等方法必须再同步上下文中才能调用,否则会抛出IllegalMonitorStateException;而sleep等方法则没有这样的限制

3. wait会release掉自己所持有的所有Lock(Monitor);而sleep不会release lock。

Java中的join

You have thread T1, T2 and T3, how will you ensure that thread T2 run after T1
and thread T3 run after T2?

你有三个线程T1,T2,T3,如何使得T1执行完后再执行T2,T2执行完后再执行T3?

以下是一个可能的实现方法:

public class ThreadJoin implements Runnable {

    private final Thread joinTarget;
    public ThreadJoin(Thread joinTarget) {
        this.joinTarget = joinTarget;
    }

    @Override
    public void run() {
        if(joinTarget != null) {
            try {
                joinTarget.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("Join complete " + Thread.currentThread().getName());
        }
    }

    private static class MyThread implements Runnable {
        @Override
        public void run() {
            System.out.println("MyThread");
        }
    }    

    public static void main(String[] args) {
        Thread t1 = new Thread(new MyThread(), "Thread1");
        Thread t2 = new Thread(new ThreadJoin(t1), "Thread2");
        Thread t3 = new Thread(new ThreadJoin(t2), "Thread3");
        t1.start();
        t2.start();
        t3.start();
    }
}

Java 线程的sleep和yield方法

yield() method pauses the currently executing thread temporarily for giving a
chance to the remaining waiting threads of the same priority to execute.

yield方法临时停止当前线程的执行,给其他的和当前线程同样优先级的线程一个执行的机会。

If there is no waiting thread or all the waiting threads have a lower priority
then the same thread will continue its execution.

如果在调度池中没有等待的线程或者所有等待的线程的优先级没有调用yield线程的优先级高,当前线程继续执行。

The yielded thread when it will get the chance for execution is decided by the
thread scheduler whose behavior is vendor dependent.

什么时候执行已经yield的线程是由线程调度器来决定的,这和JVM的实现有关。

sleep() causes the current thread to suspend execution for a specified period.

sleep方法使得当前执行的程序停止一段时间,这时线程会让出CPU来给其它的线程。

This is an efficient means of making processor time available to the other
threads of an application or other applications that might be running on a
computer system.

这样可以使得同一个程序的线程或者别的程序有CPU时间来执行自己。

The sleep method can also be used for pacing and waiting for another thread
with duties that are understood to have time requirement.

sleep方法也可以用来等待其它线程,但是有时间限制罢了。

sleep method in Java has two variants one which takes millisecond as sleeping
time while other which takes both mill and nano second for sleeping duration.

sleep方法有两个重载的方法,一个用毫秒作为参数,另外一个用毫秒和纳秒作为参数。

sleep(long millis)
sleep(long millis,int nanos)

http://www.tkhts.com/core-java/multithreading/java-thread-scheduler.jsp

PS:

Java Thread Scheduler
The JVM is based on Preemptive and priority based scheduling algorithm .

The thread with more priority is given first preference than the thread with
less priority.

The thread with more priority relinquishes (empties) the thread with less
priority that is being executed. ?

If the threads of equal priority are in the pool, the waiting time is taken in
consideration.

Nature of threads sometimes affects. The daemon threads are given less
importance and are executed only when no other thread is available for
execution.