Does anyone know if I can find a list of where the line break (_) is no longer required. So far I notice parameter lists and attributes now work without the line break char.
Technically speaking, it's called a line continuation character.
This is not a feature of the .NET Framework version, it's a feature of the compiler. The first version to support it is VB.NET 10, the one included with Visual Studio 2010.
The new feature is documented here, including a nice table listing where continuation is implicit.
Visual Basic is a line-oriented language that uses clear, English-like syntax to enhance readability. But that often results in code that runs up against the 80-character-per-line limit, forcing developers to scroll a lot. You can use the underscore character to tell the compiler that it should keep processing the next line as part of the current one (that is, treat multiple physical lines as a single, logical line). But having to type underscores repeatedly has always been annoying, and in fact, for years the No. 1 feature request has been for the compiler to “just figure it out.”
Well, in Visual Basic 2010, the compiler can. It now knows which tokens (such as commas, parentheses and operators) tend to occur right before the line-continuation character, and it inserts the character so developers no longer need to. For example, ending a Visual Basic statement with a comma is never legal; the compiler knows this, so when it sees a token stream that looks like {comma, enter}, it infers the presence of the line continuation character
[ . . . ]
As you can see, there are more than 60 places where the language doesn’t require underscores. (In fact, none of the code samples in this article required the line-continuation character.) Of course, you can still use the underscore, so code from previous versions of Visual Basic will still compile as expected.
The rules for where you can break a line haven't changed. You just no longer need the _ at all with the later compilers.
Related
The CMake documentation on generator expressions is fairly clear that "A common mistake is to try to split a generator expression across multiple lines with indenting". Here is the example they give:
# WRONG: New lines and spaces all treated as argument separators, so the
# generator expression is split and not recognized correctly.
target_compile_definitions(tgt PRIVATE
$<$<AND:
$<CXX_COMPILER_ID:GNU>,
$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,5>
>:HAVE_5_OR_LATER>
)
My experience is that using multiple lines with indenting works exactly as I'd hope. For example, the following code produces the exact results I would naively expect with the use of whitespace and indentation:
target_compile_options(common_interface INTERFACE
$<$<CXX_COMPILER_ID:MSVC>:
/W4 # Turn on warnings
/WX # Turn warnings into errors
>
$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:
-Wall # Turn on warnings
-Wextra # Turn on warnings
-Werror # Turn warnings into errors
>
)
As I understand the CMake documentation, each line here would be added as a separate compile option (e.g., $<$<CXX_COMPILER_ID:MSVC>:), but that is clearly not the case since the generated build files show the flags come through correctly.
My questions are:
What am I missing? Is the issue only with certain types of expressions (e.g., logical operators)? Has the behavior changed and the documentation is out of date? or maybe the documentation needs to be enhanced to clarify the restrictions and expected behavior?
Is it safe to continue using whitespace and indentation in some circumstances?
My suspicion is that the resulting true_string (or false_string in $<IF:condition,true_string,false_string>) of a conditional expression may contain whitespace, but the other arguments of an expression cannot be broken.
Tsyvarev's comments to the question are on the money, but I'll give a more formal answer as both one of the CMake maintainers and the author of the generator expression documentation you linked to. The TLDR version is "The docs describe what you can rely on. Don't rely on implementation details that are outside that and which may change.".
The documentation makes clear where you are required to use quoting to ensure robust behavior. Splitting a genex across multiple lines or whitespace has never been officially supported. Sometimes it might appear to work, but that is by coincidence, not by design. Just because you found a case that happens to work in some range of CMake versions, you shouldn't assume that is supported behavior, especially when the documentation now explicitly calls that out as unsupported. There is no promise that such unsupported behavior will continue to work in future releases.
To be absolutely clear, the direct answers to your questions are:
What am I missing? Is the issue only with certain types of expressions (e.g., logical operators)? Has the behavior changed and the documentation is out of date? or maybe the documentation needs to be enhanced to clarify the restrictions and expected behavior?
The documentation is up to date, and I don't know how to make things clearer than what the existing documentation already says. You're asking about things that go directly against that documentation. The aspects you're asking about are not things we intend to document because they are specifically not intended to be supported behavior! Furthermore, CMake's behavior in this area may well have changed over different versions, but it has never been promised to be stable, since it has never been part of CMake's documented API.
Is it safe to continue using whitespace and indentation in some circumstances?
No. The current documentation should make it very clear what's safe and what isn't. If you're asking if something that contradicts that documentation is safe, well, it should hopefully be clear that my answer is still "No". ;)
Footnote
People failing to quote their generator expressions has been one of the most frequently reported problems (or more accurately, the cause of reported problems) in the CMake forums and issue tracker. It kept biting people over and over, to the point where I wrote a Quoting In CMake blog article about quoting in general and I also added the Whitespace And Quoting section to the generator expressions manual in the official CMake docs (that update appeared with CMake 3.24).
I have posted on this before, but couldn't find a simple example. Here's one. I had some code commented out. Part if it was a comment. I used un-comment to turn the code back on for testing. And so this...
'check to see if this is a "simple" struct that has only basic types inside, not additional embedded type 5's
Turned into this...
check to see if this Is a "simple" struct that has only basic types inside, Not additional embedded type 5's
Look at the Is and Not. This isn't happening on all keywords, it appears that it's primarily Linq related terms get re-camel cased - Is, On, Where etc. And that's weird, because I don't have or use Linq in any of my projects.
This is annoying, but what is actually damaging is when this happens inside quotes. Let's say you had something like this...
'this is a "really long comment that I want to split into two lines"
Now I place my cursor in front of, say, "I" and hit return. This produces a second line with a trailing quote. Now every keyword in the entire file from that point on is re-cased, because there's an open quote confusing VS. Now my git diff is basically screwed.
Does anyone have any suggestions on what might be happening and how to turn it off?
The re-casing of keywords is a feature of "Pretty listing (reformatting) of code". This feature was less aggressive in VS versions earlier then VS2015 and did not run un-commenting a line.
To disable it go to:
Tools Menu->Options->Text Editor->Basic-> Advanced-> Editor help section
and uncheck "Pretty listing (reformatting) of code".
I am using ANTLR4 to parse code in my Netbeans Platform application. I have successfully implemented syntax highlighting using ANTLR4 and Netbeans mechanisms.
I have also implemented a simple code completion for two of my tokens. At the moment I am using a simple implementation from a tutorial, which searches for a whitespace and starts the completion process from there. This works, but it deems the user to prefix a whitespace before starting code completion.
My question: is it possible or even contemplated using ANTLR's lexer to determine which tokens are currently read from the input to determine the correct completion item?
I would appreciate every pointer in the right direction to improve this behaviour.
not really an answer, but I do not have enough reputation points to post comments.
is it possible or even contemplated using ANTLR's lexer to determine which tokens are currently read from the input to determine the correct completion item?
Have a look here: http://www.antlr3.org/pipermail/antlr-interest/2008-November/031576.html
and here: https://groups.google.com/forum/#!topic/antlr-discussion/DbJ-2qBmNk0
Bear in mind that first post was written in 2008 and current antlr v4 is very different from the one available at the time, which is why Sam’s opinion on this topic appear to have evolved.
My personal experience - most of what you are asking is probably doable with antlr, but you would have to know antlr very well. A more straightforward option is to use antlr to gather information about the context and use your own heuristics to decide what needs to be shown in this context.
The ANTLRv3 grammar https://sourceware.org/git/?p=frysk.git;a=blob_plain;f=frysk-core/frysk/expr/CExpr.g;hb=HEAD implements context sensitive completion of C expressions (no macros).
For instance, if fed the string:
a_struct->a<tab>
it would just lists the fields of "a_struct" starting with "a" (tab could, technically be any character or marker).
The technique it used was to:
modify a C grammar to recognize both IDENT and IDENT_TAB tokens
for IDENT_TAB capture the partial expression AST and "TOKEN_TAB" and throw them back to 'main' (there are hacks to help capture the AST)
'main' then performs a type-eval on the partial expression (compute the expression's type not value) and use that to expand TOKEN_TAB
the same technique, while not exactly ideal, can certainly be used in ANTLRv4.
I come from a C# background but am now working mostly with VB.Net. It seems to me that the above functions (and others - eg. UCase, LCase) etc. are carryovers from VB6 and before. Is the use of these functions frowned upon in VB.Net, or does it purely come down to personal preference?
My personal preference is to stay well away from them, but I'm wondering if that is just my C# prejudice.
I've come across a couple of issues - particularly with code converted from VB6 to VB.Net, where the 0 indexing of collections has meant that bugs have been introduced into code, and am therefore wary of them.
The reason that those functions are there in the first place is of course that they are part of the VB language, inherited from VB 6.
However, they are not just wrappers for methods in the framework, some of them have some additional logic that makes them different in some ways. The Mid function for example allows that you specify a range that is outside the string, and it will silently reduce the range and return the part of the string that remains. The String.Substring method instead throws an exception if you specify a range outside the string.
So, the functions are not just wrappers, they represent a different approach to programming that is more in line with Visual Basic, where you can throw just about anything at a function and almost always get something out. In some ways that is easier, as you don't have to think about all the special cases, but on the other hand you might want to get an exception instead of getting a result when you feed something unreasonable to a function. When debugging, it's often easier if you get the exception as early as possible instead of trying to trace back where a faulty value comes from.
Those options are for backward compatibility.
But, it will be better for people to use framework classes/methods to ensure consistency.
Having said that, VB6 functions are easy to understand. So, it should not be an issue for someone who has the VB background.
EDIT: Also, some of the overloads available with framework classes, might not be available with an equivalent of a simple VB6 like statement. I cannot remember of any, as of now - But this is what I think, could be a better reason to use framework classes/methods.
There will be special cases, but, Hands down, use the VB6 versions, unless you care about the difference between a string being "" and Nothing.
I was working on a big project where different programmers using both ways, the code where people used MyString.SubString(1) was blowing up while Mid(MyString,2) was working.
The two main errors for this example: (Which apply in various ways to others as well)
(1) String can be nothing and you have to check before running a method on it. Limitation of the OO notation: You can't call a member method if the object is nothing, even if you want 'nothing' or (empty object) back. Even if this were solved by using nullable/stub objects for strings (which you kind of can using "" or string.empty), you'd still have to ensure they're initialized properly - or, as in our case - convert Nothing to "" when receiving strings from library calls beyond our control.
You are going to have strings that are Nothing. 90% of the time you'll want it to mean "". with .SubString, you always have to check for nothing. With the VB versions, only the 10% about which you'll care.
(2) Specifically with the Mid example, again, 90% of the time if you want chars 3-10 of a 2 char string, you'll want to see "" returned, not have it throw an exception! In fact, you'll rarely want an exception: you'll have to check first for the proper length and code how it should behave (there is usually a defined behaviour, at the very least, a data entry error, for which you don't want to throw an exception).
So you're checking 100% of the time with the .Net versions and rarely with the VB versions.
.Net wanted to keep everything into the object-oriented philosophy. But strings are a little different than most objects used in subtle ways. MS-Basic wasn't thinking about this when they made the functions, it just got lucky - one of the strengths of functions is that they can handle null objects.
For our project, one may ask how Nothing strings got into our flow in the first place. But in the end, the decision of some programmers to use the .Net functions meant avoidable service calls, emergency bug fixes, and patches. Save yourself the trouble.
I would avoid them. Since you've mentioned them it sounds as though you've inherited some VB6 code that was possibly converted to a VB.NET project. Otherwise, if it was a new VB.NET project, I see no value in using the VB6 methods.
I've been on a few VB6 to VB.NET conversion projects. While I am familiar with the names and the difference in 0 based indexing, any code I came across got refactored to use their .NET equivalents. This was partially for consistency and to get the VB6 programmers on that project familiar with the framework. However, the other benefit I've found in refactoring is the ability to chain method calls together.
Consider the following:
Dim input As String = "hello world"
Dim result As String = input.ToUpper() ' .NET
Dim result As String = UCase(input) ' VB6
Next thing you know, I need to do more work to satisfy other requirements. Let's say I need to take the substring and get "hello," which results in the code getting updated to:
Dim result As String = input.ToUpper().Substring(0, 5) ' .NET
Dim result As String = Mid(UCase(input), 1, 5) ' VB6
Which is clearer and easier to modify? In .NET I just chain it. In VB6 I had to start at the beginning of the method, then go to the end of it and add the closing parenthesis. If it changes again or I need to remove it, in .NET I just chop off the end, but in VB6 I need to backtrack to the start and end.
I think there's value in using the .NET methods since other .NET developers that join the project later, especially those from a C# background, can easily pick it up.
Since upgrading from 4.7 to ECC6 the ABAP compiler has become a lot stricter on the use of certain statements in the OO context.
For instance you're not allowed to use the statement LIKE, but in stead have to use TYPE and internal tables does not have an implicit header line, etc.
These restrictions are explained in greater detail here
MY QUESTION: To what extent does this restriction affect your existing code-base?.
We have over a thousand "Classes" written since 1998 in OO as far as it was available at the time. For the most part each class is its own include in SE38, with the class definition and implementation together in this include.
Up to now, we could successfully change and activate these classes as long as the main program was pre-existing in 4.7. Now we are trying to use one of these older classes in a new main program for regression test purposes, and we are getting the following error:
"Within classes and interfaces, you can only use "TYPE" to refer to ABAP Dictionary types (not "LIKE" or "STRUCTURE")."
This error is valid as per the current definition of the SAP language.
I would like to know wheter the SAP interpreter continues to run old code with obsolete statements intentionally, or whether a future patch may correct this "feature" and cause these classes to stop compiling.
Each development object is tagged with a version corresponding to the SAP version it was developed on. You can see this in version management or table VRSD.
As I understand it, that is there specifically so that code with statements that have been made illegal in later versions will survive an upgrade and continue to run.
This is why, when you attach an include developed in 4.5b to a class that was developed in NW700, it won't compile. The compiler knows that this is new dev, and its applying the rules accordingly.
The ABAP community has been informed for a really long time (years) that LIKEs, work areas, RANGEs etc. are obsolete.
I don't think SAP will kill any old code, but I wouldn't count on it if I were in charge.
So can they cause it to stop compiling: yes, will they: probably not.