Erlang Plugin for NetBeans in Scala#6: Semantic Analyzer
Caoyuan Blog - - February 12, 2009With more detailed AstNodeVisitor.scala, I got the semantic information of function calls, variable definitions and references etc. It’s time to implement CSL’s SemanticAnalyzer, which is the entrance of semantic highlighting.
I then encountered a Scala’s corner case issue :-(
SemanticAnalyzer.java is a sub-class of ParserResultTask:
package org.netbeans.modules.parsing.spi;
public abstract class ParserResultTask<T extends Parser.Result> extends SchedulerTask { public abstract void run (T result, SchedulerEvent event); public abstract int getPriority ();
}
ParserResultTask’s signature in class file is:
<<TLorg/netbeans/modules/parsing/spi/Parser$Result;>Lorg/netbeans/modules/parsing/spi/SchedulerTask;>
run‘s method signature:
<(TT;Lorg/netbeans/modules/parsing/spi/SchedulerEvent;)V>
ErlangSemanticAnalyzer extended SemanticAnalyzer, so I should implement:
void run (T result, SchedulerEvent event);
which carries type parameter T from ParserResultTask<T extends Parser.Result>. But unfortunately, SemanticAnalyzer extends ParserResultTask as:
public abstract class SemanticAnalyzer extends ParserResultTask;
That is, SemanticAnalyzer erased type parameter of its parent. It’s valid in Java. But in Scala, I can not successfully extend SemanticAnalyzer anymore, since when I tried to implement “void run (T result, SchedulerEvent event)”, the scalac always complained that I did not override this method with type T. It seems scalac checks type parameter deeply, and needs sub-class to always explicitly extend parent class with type parameter. Since SemanticAnalyzer has erased type parameter, even I tried to implement “run” as:
override def run[T <: Parser.Result](result:T, event:SchedulerEvent) :Unit
scalac still complained about it.
I have no idea of how to bypass this issue. I then patched SemanticAnalyzer.java, let it carries same type parameter as its parent:
public abstract class SemanticAnalyzer<T extends Parser.Result> extends ParserResultTask<T>
Now everything works. My final code is:
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 1997-2008 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common * Development and Distribution License("CDDL") (collectively, the * "License"). You may not use this file except in compliance with the * License. You can obtain a copy of the License at * http://www.netbeans.org/cddl-gplv2.html * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the * specific language governing permissions and limitations under the * License. When distributing the software, include this License Header * Notice in each file and include the License file at * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the GPL Version 2 section of the License file that * accompanied this code. If applicable, add the following below the * License Header, with the fields enclosed by brackets [] replaced by * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * * If you wish your version of this file to be governed by only the CDDL * or only the GPL Version 2, indicate your decision by adding * "[Contributor] elects to include this software in this distribution * under the [CDDL or GPL Version 2] license." If you do not indicate a * single choice of license, a recipient has the option to distribute * your version of this file under either the CDDL, the GPL Version 2 or * to extend the choice of license to its licensees as provided above. * However, if you add GPL Version 2 code and therefore, elected the GPL * Version 2 license, then the option applies only if the new code is * made subject to such option by the copyright holder. * * Contributor(s): * * Portions Copyrighted 2009 Sun Microsystems, Inc. */
package org.netbeans.modules.erlang.editor import _root_.java.util.{HashMap,HashSet,Map,Set}
import javax.swing.text.Document
import org.netbeans.api.lexer.Token
import org.netbeans.api.lexer.TokenHierarchy
import org.netbeans.api.lexer.TokenId
import org.netbeans.modules.csl.api.{ColoringAttributes,ElementKind,OffsetRange,SemanticAnalyzer}
import org.netbeans.modules.parsing.spi.Parser
import org.netbeans.modules.parsing.spi.{Scheduler,SchedulerEvent,ParserResultTask}
import org.netbeans.modules.erlang.editor.ast.{AstDfn,AstItem,AstRef,AstRootScope}
import org.netbeans.modules.erlang.editor.lexer.LexUtil
import org.netbeans.modules.erlang.editor.lexer.ErlangTokenId /** * * @author Caoyuan Deng */
class ErlangSemanticAnalyzer extends SemanticAnalyzer[ErlangParserResult] { private var cancelled = false private var semanticHighlights :Map[OffsetRange, Set[ColoringAttributes]] = _ protected def isCancelled :Boolean = synchronized {cancelled} protected def resume :Unit = synchronized {cancelled = false} override def getHighlights :Map[OffsetRange, Set[ColoringAttributes]] = semanticHighlights override def getPriority = 0 override def getSchedulerClass = Scheduler.EDITOR_SENSITIVE_TASK_SCHEDULER override def cancel :Unit = {cancelled = true} @throws(classOf[Exception]) override def run(pResult:ErlangParserResult, event:SchedulerEvent) :Unit = { resume semanticHighlights = null if (pResult == null || isCancelled) { return } for (rootScope <- pResult.rootScope; th <- LexUtil.tokenHierarchy(pResult); doc <- LexUtil.document(pResult, true) ) { var highlights = new HashMap[OffsetRange, Set[ColoringAttributes]](100) visitItems(th.asInstanceOf[TokenHierarchy[TokenId]], rootScope, highlights) this.semanticHighlights = if (highlights.size > 0) highlights else null } } private def visitItems(th:TokenHierarchy[TokenId], rootScope:AstRootScope, highlights:Map[OffsetRange, Set[ColoringAttributes]]) :Unit = { import ElementKind._ for (item <- rootScope.idTokenToItem(th).values; hiToken <- item.idToken ) { val hiRange = LexUtil.rangeOfToken(th, hiToken.asInstanceOf[Token[TokenId]]) item match { case dfn:AstDfn => dfn.getKind match { case MODULE => highlights.put(hiRange, ColoringAttributes.CLASS_SET) case CLASS => highlights.put(hiRange, ColoringAttributes.CLASS_SET) case ATTRIBUTE => highlights.put(hiRange, ColoringAttributes.STATIC_SET) case METHOD => highlights.put(hiRange, ColoringAttributes.METHOD_SET) case PARAMETER => highlights.put(hiRange, ColoringAttributes.PARAMETER_SET) case _ => } case ref:AstRef => ref.getKind match { case METHOD => highlights.put(hiRange, ColoringAttributes.FIELD_SET) case PARAMETER => highlights.put(hiRange, ColoringAttributes.PARAMETER_SET) case _ => } } } }
}
In ErlangSemanticeAnalyzer, what you need to do is traversing all AstDfn and AstRef instances, and give them a proper ColoringAttributes set. I marked all functions as METHOD_SET(mod-method), attributes as STATIC_SET(mod-static), and function call names as FIELD_SET(mod-field), parameters as PARAMETER_SET(mod-parameter), the names in parenthesis are the corresponding names that in fontColors.xml setting file, you can define the highlighting effects in this xml file.
Again, don’t forget to register it in ErlangLanguage.scala:
override def getSemanticAnalyzer = new ErlangSemanticAnalyzer
Run it, and I got highlighted source code as:
The function declaration names are underline, parameters are bold, function calls are bold too.
I’ll gather even more detailed semantic information later, so I can identity the unused variable definitions and var references without definitions etc.
Categories: Blogs Caoyuan Blog
Comments
No comments so far, you could be the first.Add comment
Erlang on Twitter
» JafarAL (Jafar ALi ALatas): Ktemu dewa erlang sm sun go kong RT @JulianCAL: Ke langit ke-7 RT @JafarAL: Kmana malam ini ? Yg gak macet..
» VaiguntaSarathy (Vaigunta Sarathy): FS#29929: [erlang] Simplify PKGBUILD http://t.co/rDJ85DMb
» vadson27 (vadson ferreira): FS#29929: [erlang] Simplify PKGBUILD http://t.co/6Oox4Ehf
» vaibhavsingh544 (Vabhav Singh): FS#29929: [erlang] Simplify PKGBUILD http://t.co/Sjhjc2aM
» vaccumakeh (Vladimir Rostov): FS#29929: [erlang] Simplify PKGBUILD http://t.co/S86CjIjg
» ITJobs_EU_UK (ITJobs_EU_UK): #JB Ruby Developer ( Ruby / RoR Erlang LAMP ): Job Description : Ruby Developer / Software Engineer Location: Lo… http://t.co/74omWQ9m
» udzura (Uchio KONDO): 文字列操作が弱い、は今のErlangではfalseであると
» udzura (Uchio KONDO): Erlang , R14 あたりからutf-8の文字列の扱いに強くなったとのこと #shinjukuex
» winda_lestari63 (winda cliquers): gg usja di pikirin prins ank itw gjhe..RT:@Prinsia_2140
@Erlang_ABNIC @ji_bero @erlang_abnic @rb_120511
» ErlangSolutions (Erlang Solutions): Want to join the best of the best of the best? ESL is hiring 40 engineers! Join our Linkedin Group to keep updated http://t.co/CDB7qYeI
Statistics
Number of aggregated posts: 10498
Number of comments: 2115
Most recent article: May 15, 2012
Latest comments
» cheap soccer jerseys on Memory Models in Erlang vs Java: Nice discussion here,you are doing a great job. i was looking for this information. i found it on your page…
» mandesejohn on Couchbase Meetup at new HQ: Thanks for sharing experience. It should be really a great post. It should be knowledgeable and informative. Keep it up. flower delivery columbus ohio
» vermaseo on Scale means Skills: I’m surprised people are still commenting about this. George has been moved on to bigger and better things with the president for awhile now.ledikanten
