semantictokens.scala
来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 719 行 · 第 1/2 页
SCALA
719 行
case tpe0 : RefinedType => tree match { case cpt : CompoundTypeTree => buildTs(cpt.templ.parents, tpe0.parents); case _ : TypeTree => // Console.err.println("UNKNOWN TPE13: " + dbg(tree) + " tpe0=" + tpe0 + " " + tpe0.parents); case _ => if (false) Console.err.println("UNKNOWN TPE5: " + dbg(tree) + " tpe0=" + tpe0 + " " + tpe0.parents); } case tpe0 : ThisType => tree match { case stt : SingletonTypeTree => stt.ref match { case ths : This => build(ths); case _ => Console.err.println("UNKNOWN TPE11: " + tpe0 + " " + stt + " " + stt.ref + " " + stt.ref.getClass() + " " + (tree.pos).dbgString); } case tt : This => case _ : Ident => case _ : Select => case tt : TypeTree => if (false) Console.err.println("UNKNOWN TPE12: " + tpe0 + " " + tree + " " + tree.getClass() + " " + (tree.pos).dbgString); case _ => if (false) Console.err.println("UNKNOWN TPE10: " + tpe0 + " " + tree + " " + tree.getClass() + " " + (tree.pos).dbgString); } case tpe0 : SingleType => tree match { case ident : Ident => buildUse(tpe0.sym, ident.pos.offset.getOrElse(-1), tpe0); case select : Select => buildUse(tpe0.termSymbol, selectPos(select), tpe0); //Console.err.println("QUALIFIER-0: " + select.qualifier + " " + unit.source.dbg(select.qualifier.pos) + " " + tpe0.prefix + " " + tpe0.prefix.getClass() + " " + tpe0.prefix.getClass().getSuperclass() +" " + tpe0.prefix.widen + " " + tpe0.prefix.toLongString); buildT(select.qualifier, tpe0.prefix); case _ => if (false) Console.err.println("UNKNOWN TPE8: " + tree + " " + (tree.pos).dbgString + " TPE=" + tpe0 + " PRE=" + tpe0.pre + " SYM=" + tpe0.sym); } case ctype : ConstantType => case ErrorType => case _ => { if (false) Console.err.println("UNKNOWN TPE4: " + tree + " " + tpe + " " + tpe.getClass() + " " + (tree.pos).dbgString); } }; def buildTs(trees : List[Tree], types : List[Type]): Unit = if (!trees.isEmpty && !types.isEmpty) { buildT (trees.head, types.head); buildTs(trees.tail, types.tail); } else if (trees.isEmpty != types.isEmpty) { if (false && doLog) { Console.println("" + treex + " vs. " + treex.original); if (treex.original ne null) Console.println("" + treex.tpe + " vs. " + treex.original.tpe); logError("Tree vs. Type mismatch: " + trees + " " + types + " " + (tree.pos).dbgString, null); doLog = false; } };/* Martin to Sean: I don't understand why AbsTypeDef is different from AliasTypeDef. Why is the order reversed? Why two buildDefs for tree.symbol vs one for AliasTypeDef? case tree: AbsTypeDef => //Console.err.println("ABS: " + tree.symbol + " " + unit.source.dbg(tree.namePos) + " " + tree.pos.dbgString); buildDef(tree.symbol, tree.namePos) buildDef(tree.symbol, tree.pos.offset.getOrElse(-1)) build(tree.tparams); //@M build(tree.lo) build(tree.hi)*/ case tree: Bind => buildDef(tree.symbol, tree.pos.offset.getOrElse(-1)) build(tree.body) case tree: Ident => buildUse(tree.symbol, tree.pos.offset.getOrElse(-1), tree.tpe) case tree: Select => try { build(tree.qualifier) } catch { case e : Error => Console.err.println("SELECTQ: " + tree + " " + tree.qualifier + " " + (tree.qualifier.pos).dbgString); throw e; } try { if (tree.pos.offset.isDefined && tree.pos.offset.get >= unit.source.length) { if (false) Console.err.println("BAD_SELECT_QUALIFIER " + tree + " @ " + (tree.pos).dbgString); } else { //Console.err.println("SELECT-0: " + tree.symbol + " " + tree.pos.dbgString + " " + (tree.pos - selectPos(tree))); buildUse(tree.symbol, selectPos(tree), tree.tpe); } } catch { case e : Error => Console.err.println("SELECTU: " + tree + " " + tree.symbol + " " + tree.pos.dbgString); throw e; } case tree: TypeApply => //Console.err.println("TYPE_APPLY: " + tree + " " + tree.pos.dbgString); if (!tree.args.isEmpty) { //Console.err.println("ARGS: " + unit.source.dbg(tree.args0.head.pos)); } build(tree.fun) build(tree.args) case tree: Apply => build(tree.fun) build(tree.args) case tree: GenericApply => build(tree.fun) build(tree.args) case tree: Typed => build(tree.expr) build(tree.tpt) case tree: Block => if (false) { if (!tree.stats.isEmpty) Console.err.println("BLOCKS: " + tree.stats.head + " " + tree.stats.head.getClass()); Console.err.println("BLOCKE: " + tree.expr + " " + tree.expr.getClass()) } build(tree.stats) build(tree.expr) case tree: CaseDef => build(tree.pat) build(tree.guard) build(tree.body) case tree : Sequence => build(tree.trees); case tree : Assign => build(tree.lhs); build(tree.rhs); case tree : If => build(tree.cond); build(tree.thenp); build(tree.elsep); case tree : New => //Console.err.println("NEW: " + tree.tpt + " " + tree.tpt.getClass()); build(tree.tpt); case tree : Match => build(tree.selector); build(tree.cases); case tree : Return => build(tree.expr); case tree : LabelDef => build(tree.rhs); case tree : Throw => build(tree.expr); case tree : Try => build(tree.block); build(tree.catches); build(tree.finalizer); case tree : Alternative => build(tree.trees); case tree : This => if (tree.symbol ne null) buildUse(tree.symbol, tree.pos.offset.getOrElse(-1), tree.tpe); //Thread.dumpStack(); case tree : TypeDef => //Console.err.println("ALIAS: " + tree); build(tree.rhs); build(tree.tparams); buildDef(tree.symbol, tree.pos.offset.getOrElse(-1)); case tree : DocDef => build(tree.definition); case tree: Import => build(tree.expr) case tree: AppliedTypeTree => ; case tree: Annotated => ; case tree: SingletonTypeTree => ; case tree: Super => ; case tree: Literal => ; case EmptyTree => ; case _ => ; Console.err.println("BAIL: " + (tree0.pos) + " " + tree0 + " " + tree0.getClass()); } } catch { case t: Throwable => logError("Error occured at " + (tree0.pos), t) } def buildUse(term: Symbol, pos: Int, tpe: Type) = buildSym(term, pos, false, tpe) def buildDef(term: Symbol, pos: Int) = buildSym(term, pos, true, null) def buildSym(term: Symbol, pos: Int, isDef: Boolean, tpe: Type): Unit = if (term.hasFlag(Flags.ACCESSOR)) buildSym(analyzer.underlying(term), pos, isDef, tpe) else if (pos == -1) { //Console.err.println("NOPOS: " + term) //Thread.dumpStack() } else if (term != NoSymbol) { val name = NameTransformer.decode(term.name.toString).trim() val buf = unit.source.asInstanceOf[BatchSourceFile].content val cs = name.toChars var idx = 0 if (cs.length + pos > buf.length) return else while (idx < cs.length) { if (buf(pos + idx) != cs(idx)) { //Console.err.println("MISMATCH: " + name + "[" + idx + "] " + unit.source.dbg(pos)); //Thread.dumpStack(); return; } else idx = idx + 1; } if (cs.length + pos + 1 < buf.length) { if (isJavaIdentifierPart(buf(pos + cs.length))) { //Console.err.println("MISMATCH: " + name + "[last] " + unit.source.dbg(pos)); return; } } try { list.put(pos, (if (isDef) new Def(term) else new Use(term, tpe))); } catch { case e : Error => e.printStackTrace(); } } def selectPos(tree: Select): Int = if (tree.pos == NoPosition) -1 else { val buf = unit.source.asInstanceOf[BatchSourceFile].content if (tree.pos.offset.get >= buf.length) { if (false) { Console.err.println("" + tree + "@" + tree.pos + " not in " + unit.source.file.name + "[" + buf.length + "]"); Thread.dumpStack() throw new Error() } return 0 } val pos : Int = if (buf(tree.pos.offset.get) != '.') tree.pos.offset.get else { def f(x : Int) : Int = { if (buf(x).isWhitespace) f(x + 1) else x } f(tree.pos.offset.get + 1) } pos }; class TokenList { object begin extends HasNext { def prev = this def length = 0 } object end extends HasPrev { def next = this def length = 0 } // initialize begin.next0 = end end.prev0 = begin def tokenAt(offset: Int) = { cursor.seek(offset) if (cursor.token.isInstanceOf[Semantic]) cursor.token.asInstanceOf[Semantic] else null } def put(offset: Int, tok: Actual): Unit = tok match { case tok0: Semantic => put(offset, tok0) case gap: Gap => } def put(offset: Int, tok: Semantic) { cursor.seek(offset); if (cursor.token == end) { assert(offset >= cursor.offset); if (offset > cursor.offset) { // add a gap. val gap = new Gap(end.prev); gap.setLength(offset - cursor.offset); cursor.offset = offset; } // append. tok.insert(end.prev); cursor.offset = cursor.offset + tok.length; } else if (!cursor.token.isInstanceOf[Gap]) { val sem = cursor.token.asInstanceOf[Semantic]; if (sem.symbol == tok.symbol) return; if (sem.symbol != tok.symbol && sem.symbol.getClass() == tok.symbol.getClass() && sem.symbol.pos == tok.symbol.pos) return; } else { val gap = cursor.token.asInstanceOf[Gap]; if (!(offset - cursor.offset + tok.length <= gap.length)) { Console.err.println("LIST =" + this); Console.err.println("OFFSET=" + offset + " " + tok + " " + tok.length); Console.err.println(" " + cursor.offset + " " + gap.length); gap.length0 = offset - cursor.offset + tok.length //throw new Error(); } if (offset == cursor.offset) { // replace or prepend tok.prev0 = gap.prev0; if (tok.length == gap.length) { // replace gap tok.next0 = gap.next0; } else { gap.setLength(gap.length - tok.length); tok.next0 = gap; } tok.next0.prev0 = tok; tok.prev0.next0 = tok; cursor.token = tok; } else { // append val diff = (cursor.offset + gap.length) - (offset + tok.length); gap.setLength(gap.length - tok.length - diff); tok.prev0 = gap; tok.next0 = gap.next; tok.next0.prev0 = tok; tok.prev0.next0 = tok; if (diff != 0) { val gap0 = new Gap(tok); gap0.setLength(diff); } } } } override def toString(): String = { var node = begin.next var str = "" while (node != end) { str = str + " " + node node = node.next } str } object cursor { var token: Token = end var offset: Int = 0 def next: Unit = if (token == end) end else { offset = offset + token.length token = token.next } def prev: Unit = if (token.prev == begin) token else { offset = offset - token.prev.length token = token.prev } def seek(soffset: Int): Unit = if (soffset == 0) { token = begin.next offset = 0 } else { assert(soffset > 0) while (offset > soffset) prev; while (offset + token.length <= soffset && token != end) { val len0 = offset; next; } } def convertToGap = if (token.isInstanceOf[Actual]) { val ret = token.asInstanceOf[Actual].convertToGap; offset = offset - ret._1; token = ret._2; } } // add or delete characters def adjust(offset: Int, /* where */ length: Int, /* how many characters are modified */ to : Int /* length of new string */) = { cursor.seek(offset) if (cursor.token != end) { cursor.convertToGap while (cursor.offset + cursor.token.length < offset + length && cursor.token.next != end) { val save = cursor.offset cursor.next cursor.convertToGap assert(cursor.offset == save) } if (length != to && cursor.token != end) { val diff = to - length; val gap = cursor.token.asInstanceOf[Gap]; gap.setLength(gap.length + diff); }; } } } // TokenList }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?