Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add typemeasure to literalexpr #547

Merged
merged 20 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -800,7 +800,113 @@ type FSharpExpressionTreeBuilder(lexer, document, lifetime, path, projectedOffse
x.PushRangeAndProcessExpression(expr, range, ElementType.QUOTE_EXPR)

| SynExpr.Const(synConst, _) ->
x.MarkAndDone(range, x.GetConstElementType(synConst))

let getSynMeasureRange (synMeasure: SynMeasure) =
match synMeasure with
| SynMeasure.Named(range = range)
| SynMeasure.Anon range
| SynMeasure.Product(range = range)
| SynMeasure.Seq([SynMeasure.One], range)
auduchinok marked this conversation as resolved.
Show resolved Hide resolved
| SynMeasure.Seq(range = range)
| SynMeasure.Divide(range = range)
| SynMeasure.Power(range = range)
| SynMeasure.Var(range = range)
| SynMeasure.Paren(range = range) -> range
| SynMeasure.One -> failwith "should not be reached"

let processRatio (ratio: SynRationalConst) overallRange =

let rec processRatConstCase (ratio: SynRationalConst) =
match ratio with
| SynRationalConst.Integer _value ->
auduchinok marked this conversation as resolved.
Show resolved Hide resolved
let m = x.Mark()
auduchinok marked this conversation as resolved.
Show resolved Hide resolved
x.MarkAndDone(overallRange, ElementType.LITERAL_EXPR)
auduchinok marked this conversation as resolved.
Show resolved Hide resolved
x.Done(overallRange, m, ElementType.INTEGER_RAT)
| SynRationalConst.Negate ratConst ->
let m = x.Mark()
processRatConstCase ratConst
x.Done(overallRange, m, ElementType.NEGATE_RAT)
| SynRationalConst.Rational(range = range) ->
x.AdvanceToTokenOrRangeEnd(FSharpTokenType.LPAREN, range)
x.MarkAndDone(range, ElementType.RATIONAL_RAT)

let ratConstMark = x.Mark()
processRatConstCase ratio
x.Done(overallRange, ratConstMark, ElementType.RATIONAL_CONST)

let rec processMeasure (synMeasure: SynMeasure) =
match synMeasure with
| SynMeasure.Named(longId, range) ->
let namedMark = x.Mark(range)
let namedTypeMark = x.Mark(range)
x.ProcessNamedTypeReference(longId)
x.Done(range, namedTypeMark, ElementType.NAMED_TYPE_USAGE)
x.Done(range, namedMark, ElementType.NAMED_MEASURE)
| SynMeasure.Product(measure1, measure2, range) ->
let prodMark = x.Mark(range)
processMeasure measure1
processMeasure measure2
x.Done(range, prodMark, ElementType.PRODUCT_MEASURE)
| SynMeasure.One ->
() // handled in SynMeasure.Seq to have the range
auduchinok marked this conversation as resolved.
Show resolved Hide resolved
| SynMeasure.Seq([SynMeasure.One], range) ->
x.MarkAndDone(range, ElementType.ONE_MEASURE)
| SynMeasure.Seq(measures = [synMeasure]) ->
processMeasure synMeasure
| SynMeasure.Seq(synMeasures, range) ->
let seqMark = x.Mark(range)
synMeasures |> List.iter processMeasure
x.Done(range, seqMark, ElementType.SEQ_MEASURE)
| SynMeasure.Divide(measure1, measure2, range) ->
let divMark = x.Mark(range)
processMeasure measure1
processMeasure measure2
x.Done(range, divMark, ElementType.DIVIDE_MEASURE)
| SynMeasure.Power(measure = synMeasure; power = ratio; range = range) ->
let powerMark = x.Mark(range)
processMeasure synMeasure

let measureRange = getSynMeasureRange synMeasure
let ratioRange = Range.mkRange range.FileName measureRange.End range.End
x.AdvanceToTokenOrRangeEnd(FSharpTokenType.SYMBOLIC_OP, ratioRange) // advance to ^ or ^-
x.AdvanceLexer() // advanve beyond ^ or ^-
auduchinok marked this conversation as resolved.
Show resolved Hide resolved
processRatio ratio ratioRange

x.Done(range, powerMark, ElementType.POWER_MEASURE)
| SynMeasure.Anon range ->
// horrible workaround for a bug in FCS:
// currently the range of SynMeasure.Anon spans over all of the "<_>"
// construct a new range not including the GREATER
let endLine, endColumn =
if range.EndColumn > 0 then
range.EndLine, range.EndColumn - 1
else
range.EndLine - 1, range.EndColumn
auduchinok marked this conversation as resolved.
Show resolved Hide resolved
let endBeforeGreater = Position.mkPos endLine endColumn
let r = Range.mkRange range.FileName range.Start endBeforeGreater
x.AdvanceToTokenOrRangeEnd(FSharpTokenType.IDENTIFIER, range)
x.MarkAndDone(r, ElementType.ANON_MEASURE)
| SynMeasure.Paren(synMeasure, range) ->
let parenMark = x.Mark(range)
processMeasure synMeasure
x.Done(range, parenMark, ElementType.PAREN_MEASURE)
| SynMeasure.Var(synTypar, range) ->
let mark = x.Mark(range)
x.ProcessTypeParameter(synTypar)
x.Done(range, mark, ElementType.VAR_MEASURE)

let mark = x.Mark(range)

match synConst with
| SynConst.Measure(_synConst, _constantRange, synMeasure) ->
x.AdvanceToTokenOrRangeEnd(FSharpTokenType.LESS, range)
let typeMeasureMark = x.Mark(range)
processMeasure synMeasure
x.AdvanceTo(range.End)
x.Done(typeMeasureMark, ElementType.UNIT_OF_MEASURE_CLAUSE)
| _ -> ()

x.Done(range, mark, x.GetConstElementType(synConst))

| SynExpr.Typed(expr, synType, _) ->
let typeRange = synType.Range
Expand Down
71 changes: 71 additions & 0 deletions ReSharper.FSharp/src/FSharp.Psi/src/FSharp.psi
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,78 @@ unitExpr options { stubBase="UnitExpressionBase"; }:
RPAREN<RPAREN, RParen>;

literalExpr options { stubBase="FSharpExpressionBase"; }:
literalToken
unitOfMeasureClause<MEASURE, UnitOfMeasure>?;

unitOfMeasureClause:
LESS
unitOfMeasure<MEASURE, Measure>
GREATER;

interface unitOfMeasure:
namedMeasure |
productMeasure |
seqMeasure |
divideMeasure |
powerMeasure |
oneMeasure |
anonMeasure |
varMeasure |
parenMeasure;

namedMeasure:
typeUsage<TYPE_USAGE, TypeUsage>;

productMeasure:
unitOfMeasure<MEASURE_1, Measure1>
STAR
unitOfMeasure<MEASURE_2, Measure2>;

seqMeasure:
unitOfMeasure<MEASURE, Measures>*;

divideMeasure:
unitOfMeasure<MEASURE_1, Measure1>
auduchinok marked this conversation as resolved.
Show resolved Hide resolved
SYMBOLIC_OP
unitOfMeasure<MEASURE_2, Measure2>;

powerMeasure:
unitOfMeasure<MEASURE, Measure>
powerClause<POWER, Power>;

oneMeasure:
literalToken;

anonMeasure:
UNDERSCORE;

varMeasure:
typeParameterId<TYPE_PARAMETER_ID, TypeParameterId>;

parenMeasure:
LPAREN<LPAREN, LParen>
unitOfMeasure<MEASURE, Measure>
RPAREN<RPAREN, RParen>;

powerClause:
SYMBOLIC_OP
rationalConst<RATIONAL_CONST, RationalConst>;

rationalConst:
integerRat |
rationalRat |
negateRat;

integerRat:
literalToken;

rationalRat:
LPAREN<LPAREN, LeftParen>
literalToken
RPAREN<RPAREN, RightParen>;

negateRat:
rationalConst<RATIONAL_CONST, RationalConst>;

typedExpr options { stubBase="FSharpExpressionBase"; }:
fSharpExpression<EXPR, Expression>
Expand Down
2 changes: 2 additions & 0 deletions ReSharper.FSharp/src/FSharp.Psi/src/Parsing/ParserMessages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public class ParserMessages
public const string IDS_F_SHARP_PATTERN = "";
public const string IDS_LITERAL_PAT = "";
public const string IDS_CONST_PAT = "";
public const string IDS_TYPE_MEASURE = "";
public const string IDS_RATIONAL_CONST = "";
public const string IDS_F_SHARP_IDENTIFIER = "";
public const string IDS_REFERENCE_NAME_OWNER_PAT = "";
public const string IDS_REFERENCE_PAT = "";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Module

[<Measure>] type t
let i = 1<t{caret}>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Module

[<Measure>] type zzz
let i = 1<zzz>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
123<_>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Language: PsiLanguageType:F#
IFSharpImplFile
IAnonModuleDeclaration
IExpressionStatement
IChameleonExpression
ILiteralExpr
FSharpToken(type:INT32, text:123)
IUnitOfMeasureClause
FSharpTokenType+LessTokenElement(type:LESS, text:<)
IAnonMeasure
FSharpIdentifierToken(type:IDENTIFIER, text:_)
FSharpTokenType+GreaterTokenElement(type:GREATER, text:>)
NewLine(type:NEW_LINE, text:\n) spaces:"\n"

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
123<kg / s>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Language: PsiLanguageType:F#
IFSharpImplFile
IAnonModuleDeclaration
IExpressionStatement
IChameleonExpression
ILiteralExpr
FSharpToken(type:INT32, text:123)
IUnitOfMeasureClause
FSharpTokenType+LessTokenElement(type:LESS, text:<)
IDivideMeasure
INamedMeasure
INamedTypeUsage
ITypeReferenceName
Comment on lines +12 to +13
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just realized: perhaps a type usage wasn't needed here, and having just a type reference would be enough for features like Rename. We should probably try removing it when updating this code after FCS is updated.

FSharpIdentifierToken(type:IDENTIFIER, text:kg)
Whitespace(type:WHITE_SPACE, text: ) spaces:" "
FSharpIdentifierToken(type:SYMBOLIC_OP, text:/)
Whitespace(type:WHITE_SPACE, text: ) spaces:" "
INamedMeasure
INamedTypeUsage
ITypeReferenceName
FSharpIdentifierToken(type:IDENTIFIER, text:s)
FSharpTokenType+GreaterTokenElement(type:GREATER, text:>)
NewLine(type:NEW_LINE, text:\n) spaces:"\n"

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
123</kg>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Language: PsiLanguageType:F#
IFSharpImplFile
IAnonModuleDeclaration
IExpressionStatement
IChameleonExpression
ILiteralExpr
FSharpToken(type:INT32, text:123)
IUnitOfMeasureClause
FSharpTokenType+LessTokenElement(type:LESS, text:<)
IDivideMeasure
FSharpIdentifierToken(type:SYMBOLIC_OP, text:/)
INamedMeasure
INamedTypeUsage
ITypeReferenceName
FSharpIdentifierToken(type:IDENTIFIER, text:kg)
FSharpTokenType+GreaterTokenElement(type:GREATER, text:>)
NewLine(type:NEW_LINE, text:\n) spaces:"\n"

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
123<kg>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Language: PsiLanguageType:F#
IFSharpImplFile
IAnonModuleDeclaration
IExpressionStatement
IChameleonExpression
ILiteralExpr
FSharpToken(type:INT32, text:123)
IUnitOfMeasureClause
FSharpTokenType+LessTokenElement(type:LESS, text:<)
INamedMeasure
INamedTypeUsage
ITypeReferenceName
FSharpIdentifierToken(type:IDENTIFIER, text:kg)
FSharpTokenType+GreaterTokenElement(type:GREATER, text:>)
NewLine(type:NEW_LINE, text:\n) spaces:"\n"

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
123<1>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Language: PsiLanguageType:F#
IFSharpImplFile
IAnonModuleDeclaration
IExpressionStatement
IChameleonExpression
ILiteralExpr
FSharpToken(type:INT32, text:123)
IUnitOfMeasureClause
FSharpTokenType+LessTokenElement(type:LESS, text:<)
IOneMeasure
FSharpToken(type:INT32, text:1)
FSharpTokenType+GreaterTokenElement(type:GREATER, text:>)
NewLine(type:NEW_LINE, text:\n) spaces:"\n"

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
123<1 * kg>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Language: PsiLanguageType:F#
IFSharpImplFile
IAnonModuleDeclaration
IExpressionStatement
IChameleonExpression
ILiteralExpr
FSharpToken(type:INT32, text:123)
IUnitOfMeasureClause
FSharpTokenType+LessTokenElement(type:LESS, text:<)
IProductMeasure
IOneMeasure
FSharpToken(type:INT32, text:1)
Whitespace(type:WHITE_SPACE, text: ) spaces:" "
FSharpTokenType+StarTokenElement(type:STAR, text:*)
Whitespace(type:WHITE_SPACE, text: ) spaces:" "
INamedMeasure
INamedTypeUsage
ITypeReferenceName
FSharpIdentifierToken(type:IDENTIFIER, text:kg)
FSharpTokenType+GreaterTokenElement(type:GREATER, text:>)
NewLine(type:NEW_LINE, text:\n) spaces:"\n"

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
123<1/kg>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Language: PsiLanguageType:F#
IFSharpImplFile
IAnonModuleDeclaration
IExpressionStatement
IChameleonExpression
ILiteralExpr
FSharpToken(type:INT32, text:123)
IUnitOfMeasureClause
FSharpTokenType+LessTokenElement(type:LESS, text:<)
IDivideMeasure
IOneMeasure
FSharpToken(type:INT32, text:1)
FSharpIdentifierToken(type:SYMBOLIC_OP, text:/)
INamedMeasure
INamedTypeUsage
ITypeReferenceName
FSharpIdentifierToken(type:IDENTIFIER, text:kg)
FSharpTokenType+GreaterTokenElement(type:GREATER, text:>)
NewLine(type:NEW_LINE, text:\n) spaces:"\n"

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
123<(1)>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Language: PsiLanguageType:F#
IFSharpImplFile
IAnonModuleDeclaration
IExpressionStatement
IChameleonExpression
ILiteralExpr
FSharpToken(type:INT32, text:123)
IUnitOfMeasureClause
FSharpTokenType+LessTokenElement(type:LESS, text:<)
IParenMeasure
FSharpTokenType+LparenTokenElement(type:LPAREN, text:()
IOneMeasure
FSharpToken(type:INT32, text:1)
FSharpTokenType+RparenTokenElement(type:RPAREN, text:))
FSharpTokenType+GreaterTokenElement(type:GREATER, text:>)
NewLine(type:NEW_LINE, text:\n) spaces:"\n"

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
123<1 1 1>
Loading