diff -r 9cebfd34c0f4 -r c2938013239e SyntaxHighlighter2.st --- a/SyntaxHighlighter2.st Wed Feb 05 19:59:07 2014 +0100 +++ b/SyntaxHighlighter2.st Wed Feb 05 19:59:09 2014 +0100 @@ -26,7 +26,8 @@ "{ Package: 'stx:libtool' }" SyntaxHighlighter subclass:#SyntaxHighlighter2 - instanceVariableNames:'elements lastVariableElements lastSelectorElement' + instanceVariableNames:'elements lastVariableElements lastSelectorElement + ignoreBadIdentifier' classVariableNames:'' poolDictionaries:'' category:'Interface-CodeView-Syntax' @@ -132,16 +133,54 @@ "format (recolor) an expression in a given class. Return the text containing font changes and color information." - ^ self - format:aString parsingWith:[:parser | parser expression] - in:aClass elementsInto:elements + |parser tree text endPos| + + aString isNil ifTrue:[^ nil]. + + parser := self for:(ReadStream on:aString string) in:aClass. + parser elements: elements. + parser ignoreErrors:true. + parser ignoreWarnings:true. + parser sourceText:(text := aString string asText). + "/ use an array here - this can be changed much faster using #at:put: + text emphasisCollection:(Array new:aString size). + + parser nextToken. + tree := parser "expression"statementList. + "/ now, convert the emphasis-array to a runArray + text emphasisCollection:(text emphasis asRunArray). + + tree == #Error ifTrue:[ + "/ mhmh - which is better ... + "/ alternative1: color rest after error in red +"/ text +"/ emphasizeFrom:(parser sourceStream position) +"/ to:text size +"/ with:(#color->Color red). + + + "/ alternative2: take original emphasis for rest + + endPos := parser sourceStream position1Based. + endPos >= text size ifTrue:[ + ^ text + ]. + ^ ((text copyTo:endPos) , (aString copyFrom:(endPos+1))). + + "/ alternative3: no emphasis for rest. + +"/ ^ text "/ aString + ]. + ^ text " self - formatExpression:'(1 + 2) max:5' - in:UndefinedObject - elementsInto:(OrderedCollection new) + formatExpression:'(1 + 2) max:5' + in:UndefinedObject " + + "Created: / 25-07-2010 / 08:56:05 / Jan Vrany " + "Modified: / 25-07-2010 / 10:57:00 / Jan Vrany " ! formatMethod:aString in:aClass using:preferencesOrNil elementsInto: elements @@ -169,7 +208,7 @@ Error handle:[:ex | ex creator isHandled ifTrue:[ - ex reject. + ex reject. ]. (self parseErrorSignal handles:ex) ifFalse:[ "Parse error may happen when re-formatting incomplete code while editing" @@ -196,9 +235,9 @@ eColor notNil ifTrue:[ "/ mhmh - which is better ... "/ alternative1: color rest after error in red - text + text emphasizeFrom:(highlighter sourceStream position + 1) - to:text size + to:text size with:(#color->eColor). ] ifFalse:[ "/ alternative2: take original emphasis for rest @@ -211,11 +250,11 @@ ]. "/ alternative3: no emphasis for rest. ]. - ^text + ^text ] " self - formatMethod:'foo + formatMethod:'foo ^ self bar:''hello''. ' , (Character doubleQuote asString) , 'some comment' , (Character doubleQuote asString) , ' @@ -225,6 +264,7 @@ "Modified: / 22-08-2006 / 13:32:04 / cg" "Created: / 05-07-2011 / 10:39:21 / cg" + "Modified: / 28-05-2013 / 22:45:02 / Jan Vrany " ! formatStatementList:aString in:aClass elementsInto: elements @@ -249,12 +289,19 @@ ^ elements ! -elements:something +elements:aParseTreeIndex "the element collection, to collect variables, selectors etc. into" - elements := something. + elements := aParseTreeIndex. "Modified (comment): / 21-08-2011 / 09:13:31 / cg" +! + +tree: aParseNode + super tree: aParseNode. + elements tree: aParseNode + + "Created: / 16-02-2012 / 09:56:17 / Jan Vrany " ! ! !SyntaxHighlighter2 methodsFor:'initialization'! @@ -262,16 +309,323 @@ initialize super initialize. - elements := SortedCollection new. + elements := ParseTreeIndex new. lastVariableElements := Dictionary new. "Created: / 14-02-2010 / 13:08:27 / Jan Vrany " - "Modified: / 25-06-2010 / 13:04:37 / Jan Vrany " "Modified: / 21-08-2011 / 09:37:35 / cg" + "Modified: / 16-02-2012 / 09:59:58 / Jan Vrany " ! ! !SyntaxHighlighter2 methodsFor:'parsing-expressions'! +_binaryExpressionFor:receiverArg + "parse a binary-expression; return a node-tree, nil or #Error" + + |receiver expr arg sel pos1 pos2 lno| + + receiver := receiverArg. + (receiver == #Error) ifTrue:[^ #Error]. + + "special kludge: since Scanner cannot know if -digit is a binary + expression or a negative constant, handle cases here" + + [(tokenType == #BinaryOperator) + or:[(tokenType == $|) + or:[(tokenType == $^ and:[parserFlags allowCaretAsBinop]) + or:[((tokenType == #Integer) or:[tokenType == #Float]) + and:[tokenValue < 0]]]] + ] whileTrue:[ + "/ kludge alarm: in a function-call argList, #, is not a binarySelector + inFunctionCallArgument == true ifTrue:[ + ((tokenType == #BinaryOperator) and:[tokenName = ',']) ifTrue:[ + ^ receiver + ]. + ]. + + pos1 := tokenPosition. + lno := tokenLineNr. + + "/ kludge alarm: bar, caret and minus are not scanned as binop + (tokenType == $|) ifTrue:[ + sel := '|'. + sel := self selectorCheck:sel for:receiver position:tokenPosition to:tokenPosition. + self nextToken. + ] ifFalse:[ + (tokenType == $^) ifTrue:[ + sel := '^'. + sel := self selectorCheck:sel for:receiver position:tokenPosition to:tokenPosition. + self nextToken. + ] ifFalse:[ + (tokenType == #BinaryOperator) ifTrue:[ + sel := tokenName. + sel := self selectorCheck:sel for:receiver position:tokenPosition to:(tokenPosition + tokenName size - 1). + self nextToken + ] ifFalse:[ + sel := '-'. + token := tokenValue := tokenValue negated. + tokenPosition := tokenPosition + 1. "/ to skip the sign + ] + ]. + ]. + + pos2 := pos1 + sel size - 1. + self markSelector:sel from:pos1 to:pos2 receiverNode:receiver. + lastSelectorElement := nil. + + arg := self unaryExpression. + (arg == #Error) ifTrue:[^ #Error]. + + expr := BinaryNode receiver:receiver selector:sel arg:arg fold:foldConstants. + expr isErrorNode ifTrue:[ + self parseError:(expr errorString) position:pos1 to:tokenPosition. + errorFlag := false. "ok, user wants it - so he'll get it" + expr := BinaryNode receiver:receiver selector:sel arg:arg fold:nil. + ]. + expr lineNumber:lno. + expr selectorPosition:pos1. + + self checkPlausibilityOf:expr from:pos1 to:pos2. + parseForCode ifFalse:[ + self rememberSelectorUsed:sel receiver:receiver + ]. + receiver := expr. "/ for next message + ]. + ^ receiver + + "Modified: / 09-01-1998 / 19:05:18 / stefan" + "Modified: / 14-02-2010 / 17:54:53 / Jan Vrany " + "Modified: / 19-01-2012 / 10:46:49 / cg" + "Created: / 16-02-2012 / 21:54:28 / Jan Vrany " +! + +_keywordExpressionFor:receiverArg + "parse a keyword-expression; return a node-tree, nil or #Error. + + keywordExpression ::= binaryexpression + | { KEYWORD-PART binaryExpression } + " + + |expr receiver sel arg args posR1 posR2 pos1 pos2 lno positions constVal| + + receiver := receiverArg. + posR1 := tokenPosition. + (tokenType == #Keyword) ifFalse:[^ receiver]. + + pos1 := posR2 := tokenPosition. + pos2 := tokenPosition + tokenName size - 1. + positions := OrderedCollection with:(pos1 to:pos2). + sel := tokenName. + lno := tokenLineNr. + self nextToken. + arg := self binaryExpression. + (arg == #Error) ifTrue:[^ #Error]. + args := Array with:arg. + [tokenType == #Keyword] whileTrue:[ + sel := sel , tokenName. + pos2 := tokenPosition + tokenName size - 1. + positions add:(tokenPosition to:pos2). + self nextToken. + arg := self binaryExpression. + (arg == #Error) ifTrue:[^ #Error]. + args := args copyWith:arg. + ]. + + positions do:[:p | + self markSelector:sel from:p start to:p stop receiverNode:receiver. + ]. + lastSelectorElement := nil. + sel := self selectorCheck:sel for:receiver positions:positions. + + ignoreWarnings ifFalse:[ + (Class definitionSelectors includes:sel) ifTrue:[ + (receiver isVariable and:[receiver isUndeclared]) ifTrue:[ + "this is not an error - the undefined class may be loaded after this code!!" + self warning:('as yet undefined superclass: ' , receiver name) position:pos1 to:pos2. + ]. + ]. + ]. + + expr := MessageNode receiver:receiver selector:sel args:args fold:foldConstants. + expr isErrorNode ifTrue:[ + self parseError:(expr errorString) position:pos1 to:pos2. + errorFlag := false. "ok, user wants it - so he'll get it" + expr := MessageNode receiver:receiver selector:sel args:args fold:nil. + ]. + expr lineNumber:lno. + self checkPlausibilityOf:expr from:pos1 to:pos2. + parseForCode ifFalse:[ + self rememberSelectorUsed:sel receiver:receiver + ]. + +"/ (contextToEvaluateIn isNil and:[selfValue isNil]) ifTrue:[ "/ do not check this for doits +"/ receiver isSuper ifTrue:[ +"/ sel ~= selector ifTrue:[ +"/ self warnCommonMistake:'possible bad super message (selector should be same as in current method) ?' +"/ position:posR1 to:posR2-1 +"/ ]. +"/ ]. +"/ ]. +"/ + + (sel = #ifTrue: or:[sel = #ifFalse: or:[sel = #ifTrue:ifFalse: or:[sel = #ifFalse:ifTrue:]]]) ifTrue:[ + (expr receiver withConstantValueDo:[:val | constVal := val]) ifTrue:[ + |indexOfArgNotExecuted| + + "/ receiver evaluates to a constant + constVal == true ifTrue:[ + (sel startsWith: #ifFalse:) ifTrue:[ + indexOfArgNotExecuted := 1. + ] ifFalse:[ + indexOfArgNotExecuted := 2. + ] + ]. + constVal == false ifTrue:[ + (sel startsWith: #ifTrue:) ifTrue:[ + indexOfArgNotExecuted := 1. + ] ifFalse:[ + indexOfArgNotExecuted := 2. + ] + ]. + indexOfArgNotExecuted == 2 ifTrue:[ + args size == 1 ifTrue:[ indexOfArgNotExecuted := nil] + ]. + + indexOfArgNotExecuted notNil ifTrue:[ + |argIsNotExecuted| + + "/ self warning:'receiver is constant; arg',indexOfArgNotExecuted printString,' is never executed' position:pos1 to:tokenPosition. + argIsNotExecuted := expr args at:indexOfArgNotExecuted. + argIsNotExecuted isBlockNode ifTrue:[ + self markCommentFrom:argIsNotExecuted startPosition to:argIsNotExecuted endPosition. + ]. + ]. + ]. + ]. + + (ignoreErrors or:[ignoreWarnings]) ifFalse:[ + (sel = #and: or:[sel = #or:]) ifTrue:[ + expr arg1 isBlock ifFalse:[ + (expr arg1 isVariable + and:[ (expr arg1 name asLowercase includesString:'block')]) ifFalse:[ + self warnCommonMistake:'(possible common mistake) missing block brackets ?' + position:pos2+1 to:tokenPosition-1 + ] + ]. + ^ expr. + ]. + + (sel = #whileTrue: or:[sel = #whileFalse:]) ifTrue:[ + expr receiver isBlock ifFalse:[ + (expr receiver isVariable + and:[ (expr receiver name asLowercase includesString:'block')]) ifFalse:[ + self warnCommonMistake:'(possible common mistake) missing block brackets ?' + position:pos1 to:pos2 + ] + ]. + ^ expr. + ]. + + (sel = #ifTrue: or:[sel = #ifFalse:]) ifTrue:[ + expr receiver isMessage ifTrue:[ + (expr receiver selector = #whileTrue or:[expr receiver selector = #whileFalse]) ifTrue:[ + self warnCommonMistake:'strange receiver expression' + position:pos1 to:pos2 + ]. + ]. + ^ expr + ]. + ]. + + ^ expr. + + "Modified: / 14-02-2010 / 17:58:40 / Jan Vrany " + "Modified: / 19-01-2012 / 10:47:01 / cg" + "Created: / 16-02-2012 / 21:54:35 / Jan Vrany " +! + +_unaryExpressionFor:receiverArg + "parse a unary-expression; return a node-tree, nil or #Error" + + |receiver expr sel pos pos2 lNr arguments| + + receiver := receiverArg. + (receiver == #Error) ifTrue:[^ #Error]. + + [ self isValidUnarySelector:tokenType ] whileTrue:[ + pos := tokenPosition. + pos2 := pos + tokenName size - 1. + lNr := tokenLineNr. + sel := tokenName. + + self markSelector:sel from:pos to:pos2 receiverNode:receiver. + lastSelectorElement := nil. + + self nextToken. + tokenType == $( ifTrue:[ + parserFlags allowSqueakExtensions == true ifTrue:[ + "/ croquet/squeak extension - c/java-style arguments + arguments := self functionCallArgList. + "/ synthetic selector: foo[:[with:[with:[...]]]] + arguments notEmpty ifTrue:[ + sel := sel , ':'. + arguments size - 1 timesRepeat:[ sel := sel , 'with:' ]. + ]. + sel := self selectorCheck:sel for:receiver position:pos to:pos2. + expr := MessageNode receiver:receiver selector:sel args:arguments fold:foldConstants. + expr isErrorNode ifTrue:[ + self parseError:(expr errorString) position:pos to:pos2. + errorFlag := false. "ok, user wants it - so he'll get it" + expr := MessageNode receiver:receiver selector:sel args:arguments fold:nil. + ]. + expr lineNumber:lNr. + self checkPlausibilityOf:expr from:pos to:pos2. + parseForCode ifFalse:[ + self rememberSelectorUsed:sel receiver:receiver + ]. + ^ expr. + ]. + ]. + + sel := self selectorCheck:sel for:receiver position:pos to:pos2. + expr := UnaryNode receiver:receiver selector:sel fold:foldConstants. + expr isErrorNode ifTrue:[ + self warning:(expr errorString , '.\\If you proceed, that error will happen at runtime.') withCRs position:pos to:pos2. + errorFlag := false. "ok, user wants it - so he'll get it" + expr := UnaryNode receiver:receiver selector:sel fold:nil. + ]. + expr lineNumber:lNr. + + self checkPlausibilityOf:expr from:pos to:pos2. + parseForCode ifFalse:[ + self rememberSelectorUsed:sel receiver:receiver + ]. + + receiver := expr. "/ for next message + ]. + ^ receiver + + "Modified: / 14-02-2010 / 17:56:21 / Jan Vrany " + "Modified: / 19-01-2012 / 10:47:37 / cg" + "Created: / 16-02-2012 / 21:54:45 / Jan Vrany " +! + +binaryExpression + | node savedLastSelectorElement | + + savedLastSelectorElement := lastSelectorElement. + lastSelectorElement := nil. + node := super binaryExpression. + (lastSelectorElement notNil and:[node ~~ #Error and:[node isMessage]]) ifTrue:[ + lastSelectorElement node parent: node. + ]. + lastSelectorElement := savedLastSelectorElement. + ^node + + "Modified: / 19-01-2000 / 16:22:16 / cg" + "Created: / 16-02-2012 / 21:56:51 / Jan Vrany " +! + binaryExpressionFor:receiverArg "parse a binary-expression; return a node-tree, nil or #Error" @@ -349,132 +703,22 @@ ! expression - "parse a cascade-expression; return a node-tree, nil or #Error. - - expression ::= keywordExpression - | keywordExpression cascade - - cascade ::= ';' expressionSendPart - | cascade ';' expressionSendPart - - expressionSendPart ::= { KEYWORD binaryExpression } - | BINARYOPERATOR unaryExpression - | IDENTIFIER - " + | node savedLastSelectorElement | - |receiver arg sel args pos pos2 lno tokenEnd realReceiver positions| - - pos := tokenPosition. - receiver := self keywordExpression. - (receiver == #Error) ifTrue:[^ #Error]. - (tokenType == $;) ifTrue:[ - receiver isMessage ifFalse:[ - self syntaxError:'left side of cascade must be a message expression' - position:pos to:tokenPosition. - realReceiver := receiver. "/ only to allow continuing. - ] ifTrue:[ - realReceiver := receiver receiver. + savedLastSelectorElement := lastSelectorElement. + lastSelectorElement := nil. + node := super expression. + ((node ~~ #Error) and:[node isMessage]) ifTrue:[ + [ lastSelectorElement notNil ] whileTrue:[ + lastSelectorElement node parent: node. + lastSelectorElement := lastSelectorElement prev. ]. - [tokenType == $;] whileTrue:[ - self nextToken. - (tokenType == #Identifier) ifTrue:[ - tokenEnd := tokenPosition + tokenName size - 1. - self markSelector:tokenName from:tokenPosition to:tokenEnd receiverNode:realReceiver. - sel := tokenName. - sel := self selectorCheck:tokenName for:realReceiver position:tokenPosition to:tokenEnd. - receiver := CascadeNode receiver:receiver selector:sel. - receiver lineNumber:tokenLineNr. - self nextToken. - ] ifFalse:[ - (tokenType == #BinaryOperator) ifTrue:[ - tokenEnd := tokenPosition + tokenName size - 1. - self markSelector:tokenName from:tokenPosition to:tokenEnd receiverNode:realReceiver. - lastSelectorElement := nil. - sel := tokenName. - sel := self selectorCheck:tokenName for:realReceiver position:tokenPosition to:tokenEnd. - lno := tokenLineNr. - self nextToken. - arg := self unaryExpression. - (arg == #Error) ifTrue:[^ #Error]. - receiver := CascadeNode receiver:receiver selector:sel arg:arg. - receiver lineNumber:lno. - ] ifFalse:[ - (tokenType == #Keyword) ifTrue:[ - tokenEnd := tokenPosition + tokenName size - 1. - positions := OrderedCollection with:(tokenPosition to:tokenEnd). - pos := tokenPosition. - pos2 := tokenEnd. - lno := tokenLineNr. - sel := tokenName. - self nextToken. - arg := self binaryExpression. - (arg == #Error) ifTrue:[^ #Error]. - args := Array with:arg. - [tokenType == #Keyword] whileTrue:[ - tokenEnd := tokenPosition + tokenName size - 1. - positions add:(tokenPosition to:tokenEnd). - sel := sel , tokenName. - self nextToken. - arg := self binaryExpression. - (arg == #Error) ifTrue:[^ #Error]. - args := args copyWith:arg. - pos2 := tokenEnd - ]. - positions do:[:p | - self markSelector:sel from:p start to:p stop receiverNode:realReceiver. - ]. - lastSelectorElement := nil. - - sel := self selectorCheck:sel for:realReceiver position:pos to:pos2. - - receiver := CascadeNode receiver:receiver selector:sel args:args. - receiver lineNumber:lno. - ] ifFalse:[ - (tokenType == #Error) ifTrue:[^ #Error]. - self syntaxError:('invalid cascade; ' , tokenType printString , ' unexpected') - position:tokenPosition to:source position. - ^ #Error - ] - ] - ] - ]. - - "obscure (unspecified ?) if selector follows; Question: - - is - 'expr sel1; sel2 sel3' - - to be parsed as: - (t := expr. - t sel1. - t sel2) sel3 - - or: - (t := expr. - t sel1. - t sel2 sel3) - " - ((tokenType == #Identifier) - or:[(tokenType == #BinaryOperator) - or:[tokenType == #Keyword]]) ifTrue:[ - self syntaxError:'ambigous cascade - please group using (...)' - position:tokenPosition to:source position. - ^ #Error -"/ self warning: "syntaxError:" 'possibly ambigous cascade - please group using (...)' -"/ position:tokenPosition to:source position - 1. -"/ tokenType == #Identifier ifTrue:[ -"/ ^ self unaryExpressionFor:receiver -"/ ]. -"/ tokenType == #BinaryOperator ifTrue:[ -"/ ^ self binaryExpressionFor:receiver -"/ ]. -"/ ^ self keywordExpressionFor:receiver - ] ]. - ^ receiver + lastSelectorElement := savedLastSelectorElement. + ^node "Modified: / 19-01-2000 / 16:22:16 / cg" - "Modified: / 14-02-2010 / 17:58:57 / Jan Vrany " + "Modified: / 16-02-2012 / 23:39:15 / Jan Vrany " ! keywordExpressionFor:receiverArg @@ -621,64 +865,112 @@ unaryExpressionFor:receiverArg "parse a unary-expression; return a node-tree, nil or #Error" - |receiver expr sel pos pos2 lNr arguments| + |receiver expr sel pos pos2 lNr arguments savedLastSelectorElement| + savedLastSelectorElement := lastSelectorElement. receiver := receiverArg. (receiver == #Error) ifTrue:[^ #Error]. [ self isValidUnarySelector:tokenType ] whileTrue:[ - pos := tokenPosition. - pos2 := pos + tokenName size - 1. - lNr := tokenLineNr. - sel := tokenName. + pos := tokenPosition. + pos2 := pos + tokenName size - 1. + lNr := tokenLineNr. + sel := tokenName. - self markSelector:sel from:pos to:pos2 receiverNode:receiver. - lastSelectorElement := nil. + lastSelectorElement := nil. + self markSelector:sel from:pos to:pos2 receiverNode:receiver. - self nextToken. - tokenType == $( ifTrue:[ - parserFlags allowSqueakExtensions == true ifTrue:[ - "/ croquet/squeak extension - c/java-style arguments - arguments := self functionCallArgList. - "/ synthetic selector: foo[:[with:[with:[...]]]] - arguments notEmpty ifTrue:[ - sel := sel , ':'. - arguments size - 1 timesRepeat:[ sel := sel , 'with:' ]. - ]. - sel := self selectorCheck:sel for:receiver position:pos to:pos2. - expr := MessageNode receiver:receiver selector:sel args:arguments fold:foldConstants. - expr isErrorNode ifTrue:[ - self parseError:(expr errorString) position:pos to:pos2. - errorFlag := false. "ok, user wants it - so he'll get it" - expr := MessageNode receiver:receiver selector:sel args:arguments fold:nil. - ]. - expr lineNumber:lNr. - self checkPlausibilityOf:expr from:pos to:pos2. - ^ expr. - ]. - ]. + self nextToken. + tokenType == $( ifTrue:[ + parserFlags allowSqueakExtensions == true ifTrue:[ + "/ croquet/squeak extension - c/java-style arguments + arguments := self functionCallArgList. + "/ synthetic selector: foo[:[with:[with:[...]]]] + arguments notEmpty ifTrue:[ + sel := sel , ':'. + arguments size - 1 timesRepeat:[ sel := sel , 'with:' ]. + ]. + sel := self selectorCheck:sel for:receiver position:pos to:pos2. + expr := MessageNode receiver:receiver selector:sel args:arguments fold:foldConstants. + expr isErrorNode ifTrue:[ + self parseError:(expr errorString) position:pos to:pos2. + errorFlag := false. "ok, user wants it - so he'll get it" + expr := MessageNode receiver:receiver selector:sel args:arguments fold:nil. + ]. + lastSelectorElement node parent: expr. + expr lineNumber:lNr. + self checkPlausibilityOf:expr from:pos to:pos2. + parseForCode ifFalse:[ + self rememberSelectorUsed:sel receiver:receiver + ]. + ^ expr. + ]. + ]. - sel := self selectorCheck:sel for:receiver position:pos to:pos2. - expr := UnaryNode receiver:receiver selector:sel fold:foldConstants. - expr isErrorNode ifTrue:[ - self warning:(expr errorString , '.\\If you proceed, that error will happen at runtime.') withCRs position:pos to:pos2. - errorFlag := false. "ok, user wants it - so he'll get it" - expr := UnaryNode receiver:receiver selector:sel fold:nil. - ]. - expr lineNumber:lNr. + sel := self selectorCheck:sel for:receiver position:pos to:pos2. + expr := UnaryNode receiver:receiver selector:sel fold:foldConstants. + expr isErrorNode ifTrue:[ + self warning:(expr errorString , '.\\If you proceed, that error will happen at runtime.') withCRs position:pos to:pos2. + errorFlag := false. "ok, user wants it - so he'll get it" + expr := UnaryNode receiver:receiver selector:sel fold:nil. + ]. + expr lineNumber:lNr. + lastSelectorElement node parent: expr. - self checkPlausibilityOf:expr from:pos to:pos2. + self checkPlausibilityOf:expr from:pos to:pos2. + parseForCode ifFalse:[ + self rememberSelectorUsed:sel receiver:receiver + ]. - receiver := expr. "/ for next message + receiver := expr. "/ for next message ]. + lastSelectorElement := savedLastSelectorElement. ^ receiver - "Modified: / 14-02-2010 / 17:56:21 / Jan Vrany " "Modified: / 19-01-2012 / 10:47:37 / cg" + "Created: / 16-02-2012 / 23:50:17 / Jan Vrany " +! + +variable + | node | + + ignoreBadIdentifier := classToCompileFor isNil. + node := super variable. + ignoreBadIdentifier := false. + node isVariable ifTrue:[ + | el prevEl | + + el := elements newElementFor: node. + prevEl := lastVariableElements at:node name ifAbsent:[nil]. + prevEl notNil ifTrue:[prevEl next:el]. + lastVariableElements at:node name put:el. + elements add: el. + ]. + ^node + + "Modified: / 19-01-2000 / 16:22:16 / cg" + "Created: / 16-02-2012 / 22:21:33 / Jan Vrany " ! ! !SyntaxHighlighter2 methodsFor:'syntax detection'! +markArgumentIdentifierFrom:pos1 to:pos2 + | node el prevEl | + + super markArgumentIdentifierFrom:pos1 to:pos2. + node := VariableNode methodArgumentNamed:(sourceText string copyFrom: pos1 to: pos2). + node startPosition: pos1 endPosition: pos2. + el := elements newElementFor: node. + prevEl := lastVariableElements at:node name ifAbsent:[nil]. + prevEl notNil ifTrue:[prevEl next:el]. + lastVariableElements at:node name put:el. + elements add: el. + + "Created: / 24-07-2010 / 09:25:12 / Jan Vrany " + "Modified: / 21-08-2011 / 09:27:26 / cg" + "Modified: / 16-02-2012 / 22:34:48 / Jan Vrany " +! + markAssignedVariable:v from:pos to:endPos super markAssignedVariable:v from:pos to:endPos. (v type == #GlobalVariable) ifTrue:[^self]. @@ -686,6 +978,13 @@ self rememberVariableElementFor:v name type:v type from:pos to:endPos assigned:true ! +markBadIdentifierFrom:pos1 to:pos2 + + super markBadIdentifierFrom:pos1 to:pos2 + + "Created: / 17-03-2012 / 19:02:40 / Jan Vrany " +! + markGlobalClassIdentifierFrom:pos1 to:pos2 | name env cls | @@ -709,8 +1008,19 @@ ! markLocalIdentifierFrom:pos1 to:pos2 + | node el prevEl | + super markLocalIdentifierFrom:pos1 to:pos2. - self rememberVariableElementFor:tokenName type:#MethodVariable from:pos1 to:pos2 assigned:false + node := VariableNode methodLocalNamed:(sourceText string copyFrom: pos1 to: pos2). + node startPosition: pos1 endPosition: pos2. + el := elements newElementFor: node. + prevEl := lastVariableElements at:node name ifAbsent:[nil]. + prevEl notNil ifTrue:[prevEl next:el]. + lastVariableElements at:node name put:el. + elements add: el. + + "Modified: / 21-08-2011 / 09:27:26 / cg" + "Created: / 16-02-2012 / 22:36:41 / Jan Vrany " ! markMethodArgumentIdentifierFrom:pos1 to:pos2 @@ -725,18 +1035,35 @@ | element selectorSymbol | - super markSelector:selectorString from:pos1 to:pos2 receiverNode:aReceiverNode. + "Special hack for Java class references - I would like to have them + marked specially (and not as an error when the class is not yet loaded - + the code is correct as JavaClassAccessor loads it lazily" + (aReceiverNode isJavaPackageReference) ifTrue:[ + self + markFrom:pos1 to:pos2 + withEmphasis:preferences globalClassIdentifierEmphasis + color: preferences globalClassIdentifierColor + ] ifFalse:[ + super markSelector:selectorString from:pos1 to:pos2 receiverNode:aReceiverNode. + ]. + "don't create symbols for partial typed selectors" selectorSymbol := selectorString asSymbolIfInterned. - element := SyntaxElement from: pos1 to: pos2 type: #selector value: (selectorSymbol ? selectorString). - lastSelectorElement ifNotNil:[lastSelectorElement next: element]. + element := elements newElementFor: (SelectorNode value: selectorString from: pos1 to: pos2). + + (lastSelectorElement notNil "and:[lastSelectorElement value = selectorString]") ifTrue:[ + lastSelectorElement next: element. + ]. elements add: element. - lastSelectorElement := element. + lastSelectorElement := "(self isValidUnarySelector:tokenType)"false + ifTrue:[nil] + ifFalse:[element]. "Created: / 14-02-2010 / 17:40:09 / Jan Vrany " "Modified: / 14-02-2010 / 19:24:17 / Jan Vrany " "Modified (format): / 21-08-2011 / 09:18:21 / cg" + "Modified: / 19-04-2012 / 09:53:59 / Jan Vrany " ! markSelfFrom:pos1 to:pos2 @@ -748,12 +1075,12 @@ markUnknownIdentifierFrom:pos1 to:pos2 - classToCompileFor notNil - ifTrue:[super markUnknownIdentifierFrom:pos1 to:pos2] - ifFalse:[self markLocalIdentifierFrom: pos1 to: pos2]. + ignoreBadIdentifier == true ifTrue:[ ^ self ]. - "Created: / 24-07-2010 / 09:51:38 / Jan Vrany " - "Modified: / 02-08-2011 / 09:35:02 / cg" + super markUnknownIdentifierFrom:pos1 to:pos2 + + "Created: / 31.3.1998 / 19:09:26 / cg" + "Modified: / 31.3.1998 / 19:10:30 / cg" ! markVariable:v from:pos1 to:pos2 assigned:assigned @@ -794,14 +1121,14 @@ !SyntaxHighlighter2 class methodsFor:'documentation'! version - ^ '$Header: /cvs/stx/stx/libtool/SyntaxHighlighter2.st,v 1.18 2013-08-10 11:10:24 stefan Exp $' + ^ '$Header: /cvs/stx/stx/libtool/SyntaxHighlighter2.st,v 1.19 2014-02-05 18:59:09 cg Exp $' ! version_CVS - ^ '$Header: /cvs/stx/stx/libtool/SyntaxHighlighter2.st,v 1.18 2013-08-10 11:10:24 stefan Exp $' + ^ '$Header: /cvs/stx/stx/libtool/SyntaxHighlighter2.st,v 1.19 2014-02-05 18:59:09 cg Exp $' ! version_SVN - ^ '$Id: SyntaxHighlighter2.st,v 1.18 2013-08-10 11:10:24 stefan Exp $' + ^ '$Id: SyntaxHighlighter2.st,v 1.19 2014-02-05 18:59:09 cg Exp $' ! !