XenHat / SublimeLinter-contrib-lslint

LSL linting for Sublime Text 3
MIT License
1 stars 0 forks source link

Enhancement request for preprocessors support #6

Closed ghost closed 7 years ago

ghost commented 7 years ago

Here is issue that I've posted on lslint repo few days ago: https://github.com/Makopo/lslint/issues/47. My problem is that your plugin ignores files icluded by preprocessor and produces errors about undeclared variables.

ghost commented 7 years ago

@XenHat that is strange. I added your repository, but still WARNING: lslint deactivated, cannot locate 'lslint'. I using LSL package and have lslint file in my bin folder, so I can get acces to it from terminal, from any place.

test

XenHat commented 7 years ago

Can you show me the output from the console (or at least a few more lines)? I want to see where it tries to look. THOUGHT: Perhaps your .bashrc or .profile adds a location into your path that isn't in the environment sublime-text is started with?

I know I changed some things related to path but I have done no testing from linux to ensure it detected it properly. EDIT: Calling lslint directly works in most cases within python, I'll set up a quick environment to test.

ghost commented 7 years ago

My bin folder added to path via .bashrc and /etc/environment

test

XenHat commented 7 years ago

Hmmmm Curious. I will set up a quick Ubuntu and Dropbox (so handy) setup in a few minutes

ghost commented 7 years ago

I tried to run sublime-text exactly from this bin-folder, did not help.

XenHat commented 7 years ago

image

ghost commented 7 years ago

Added symbolic link of lslint to /bin, still not working.

XenHat commented 7 years ago

@Winterwolf fixed

ghost commented 7 years ago

@XenHat confirm! It works now. Thanks :+1:

XenHat commented 7 years ago

Np, my bad 😭

XenHat commented 7 years ago

@Sei-Lisa Concerning what doesn't work still, well... I'm not too sure how to properly describe the issue... So far, it doesn't work with scripts containing large amounts of preprocessor directives. I shall try with smaller ones.

XenHat commented 7 years ago

The following script:

default
{
    state_entry()
    {
        llOwnerSay("A thing!");
    }
}

Produces the following output:

ORIGINAL_CODE:
0    |default
1    |{
2    |    state_entry()
3    |    {
4    |        llOwnerSay("A thing!");
5    |    }
6    |} 
MCPP Output:
0    |#line 1 "<stdin>"
1    |default
2    |{
3    |    state_entry()
4    |    {
5    |        llOwnerSay("A thing!");
6    |    }
7    |}
8    |<stdin>:7: warning: End of input with no newline, supplemented newline
9    |    } 
DEBUG:: LINTER_OUT output:
ERROR:: (  9,  1): syntax error, unexpected '<', expecting $end

TOTAL:: Errors: 1  Warnings: 0

number: 9
Offset: 0
Token + offset: 9
New Line: ERROR:: (  9,  1): syntax error, unexpected '<', expecting $end
SublimeLinter: lslint output:
ERROR:: (  9,  1): syntax error, unexpected '<', expecting $end
TOTAL:: Errors: 1  Warnings: 0 
SublimeLinter: error in SublimeLinter daemon: 
SublimeLinter: -------------------- 
SublimeLinter: Traceback (most recent call last):
  File "C:\portable\Editors\Sublime Text 3\Data\Packages\SublimeLinter\lint\queue.py", line 57, in loop
    item = self.q.get(block=True, timeout=self.MIN_DELAY)
  File "./python3.3/queue.py", line 175, in get
queue.Empty

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\portable\Editors\Sublime Text 3\Data\Packages\SublimeLinter\lint\queue.py", line 65, in loop
    self.lint(view_id, timestamp)
  File "C:\portable\Editors\Sublime Text 3\Data\Packages\SublimeLinter\lint\queue.py", line 111, in lint
    self.callback(view_id, timestamp)
  File "C:\portable\Editors\Sublime Text 3\Data\Packages\SublimeLinter\sublimelinter.py", line 120, in lint
    Linter.lint_view(view, filename, code, hit_time, callback)
  File "C:\portable\Editors\Sublime Text 3\Data\Packages\SublimeLinter\lint\linter.py", line 957, in lint_view
    linter.lint(hit_time)
  File "C:\portable\Editors\Sublime Text 3\Data\Packages\SublimeLinter\lint\linter.py", line 1494, in lint
    start, end = self.highlight.full_line(line)
  File "C:\portable\Editors\Sublime Text 3\Data\Packages\SublimeLinter\lint\highlight.py", line 200, in full_line
    start = self.newlines[line] + char_offset
IndexError: list index out of range

SublimeLinter: -------------------- 
Sei-Lisa commented 7 years ago

That's an mcpp warning. Your include file doesn't seem to end in newline. That seems to be a problem in the specifications for includes in the ANSI C preprocessor. Boost::Wave, the preprocessor used in Firestorm, rejects those right away, stopping preprocessing and causing many duplicate issues in JIRA for that reason. mcpp seems to be gentler and reports a warning instead.

You can disable mcpp warnings with -W0.

Edit: No idea about the queue.Empty exception.

Sei-Lisa commented 7 years ago

So far, it doesn't work with scripts containing large amounts of preprocessor directives. I shall try with smaller ones.

That makes little sense. Any example I can examine myself?

XenHat commented 7 years ago

https://github.com/XenHat/Kemono-Body-Script/blob/72bc8869210d6a29b1937174c19e4648bd1b728f/xenhat.kemono.body.lsl

@line 1216:
-         string text = g_HoverText;
+        string text = g_HoverText;xdzfsdf

It does output something, however visual hints are non-functional somewhere else

DEBUG:: LINTER_OUT output:
ERROR:: (896,  9): syntax error, unexpected IDENTIFIER

 WARN:: (894, 16): variable `text' declared but never used.

TOTAL:: Errors: 1  Warnings: 1

number: 896
Offset: -331
Token + offset: 565
New Line: ERROR:: (565,  9): syntax error, unexpected IDENTIFIER
number: 894
Offset: -323
Token + offset: 571
New Line:  WARN:: (571, 16): variable `text' declared but never used.
=== END LINTER DEBUG ===
SublimeLinter: lslint output:
ERROR:: (565,  9): syntax error, unexpected IDENTIFIER
 WARN:: (571, 16): variable `text' declared but never used.
TOTAL:: Errors: 1  Warnings: 1 
Sei-Lisa commented 7 years ago

Why tokminoff = number + int(offset)? It used to be minus, and I don't think it works with plus.

Sei-Lisa commented 7 years ago

Also, I strongly recommend against iter_line.replace.

XenHat commented 7 years ago

Why tokminoff = number + int(offset)? It used to be minus, and I don't think it works with plus.

it worked better that way? I'm way out of my league here..

Also, I strongly recommend against iter_line.replace.

What else am I supposed to do? It doesn't modify the original string..

Sei-Lisa commented 7 years ago

a) It's not the right calculation.

b) A regex replacement would be best, but if you're not confident with them, recompose the string from the parts you separated earlier. Put them back together by adding the WARN:: ( or ERROR:: ( then the new number then the rest of the line.

XenHat commented 7 years ago

A regex replacement would be best, but if you're not confident with them, recompose the string from the parts you separated earlier. Put them back together by adding the WARN:: ( or ERROR:: ( then the new number then the rest of the line.

I purposefully avoided regex due to CPU time cost.

Sei-Lisa commented 7 years ago

Don't avoid them. it's probably more costly to perform so many splits and object creation and destruction anyway. We're talking one regex compilation per lint, and one compiled regex match per very short line. Negligible compared to the time that lslint takes to run.

Going back to this:

ORIGINAL_CODE:
0    |//
1    |//
2    |//
3    |//
4    |//
5    |//
6    |#include "x.h"
7    |default{timer(){error1;
8    |error2;
9    |error3;}}
MCPP Output:
0    |#line 1 "<stdin>"
1    |#line 7 "<stdin>"
2    |#line 1 "x.h"
3    |echo "x(){}"
4    |#line 8 "<stdin>"
5    |default{timer(){error1;
6    |error2;
7    |error3;}}
DEBUG:: LINTER_OUT output:
ERROR:: (  4,  6): syntax error, unexpected STRING_CONSTANT, expecting '('

TOTAL:: Errors: 1  Warnings: 0

number: 4
Offset: 2
Token + offset: 6
New Line: ERROR:: (  6,  6): syntax error, unexpected STRING_CONSTANT, expecting '('
SublimeLinter: lslint output:
ERROR:: (  6,  6): syntax error, unexpected STRING_CONSTANT, expecting '('
TOTAL:: Errors: 1  Warnings: 0 

The error was presumably on line 1 of the include, right? However 4 - 2 is still 2, not 1, so maybe you have to apply +2 instead of +1 inside getLastOffset.

XenHat commented 7 years ago

@Sei-Lisa That helped, but the line numbers are still wrong on my long script :( EDIT: Not exactly wrong, simply not matching the editor's view: image

892  |        }
893  |        string text = g_HoverText;xdzfsdf
894  |#line 1226 "<stdin>"
895  |        llSetText(text+"\n \n \n \n ",  <0.825,0.825,0.825> ,  0.75 );
896  |        llSetTimerEvent(10);
897  |    }
898  |}
DEBUG:: LINTER_OUT output:
ERROR:: (896,  9): syntax error, unexpected IDENTIFIER

 WARN:: (894, 16): variable `text' declared but never used.

TOTAL:: Errors: 1  Warnings: 1
XenHat commented 7 years ago

Ah, I see, it's not putting the right line number back.. D:

XenHat commented 7 years ago

I don't understand, but whatever. b92ee10e5f7634e717f82195eb71684f59610e63

Sei-Lisa commented 7 years ago

Ah, I see, it's not putting the right line number back.. D:

I can't help with that. I have no idea what's the input file or any other debug info. The script you pasted gives no errors for me. I guess you're forcing some error somewhere, but no idea where or what the output should be and what it actually is.

XenHat commented 7 years ago

This should work. image

Sei-Lisa commented 7 years ago

I can't even begin to imagine how that abs() can be correct in any possible case. Could you give an example that I can reproduce?

Edit: Specifically, I don't see how it can be an improvement in any case, beyond very specific cases similar to the specific time of the day where a stopped clock a clock running backwards gives the correct time.

Sei-Lisa commented 7 years ago

tl;dr version: revert dc92a55 and change the sense of the comparison in getLastOffset from <= to >=.

Long version that I had written when that landed on me:

Let me try to put it this way. Let's for now assume that all line numbers are zero-based, even those coming from lslint, even if it's not true. We need to operate in common units.

    a | #line b "<stdin>"
  a+1 | something
  a+2 | something else
c=a+3 | error point

What #line is saying is that a+1 should be reported as b, a+2 should be reported as b+1, a+3 should be reported as b+2, and so on.

When lslint reports an error, the error is reported at c=a+3, the line number in the preprocessed file that has the #line directives. If you have a (the line where the last #line is), b (the parameter of #line) and c (the line where the error is), how do we get and report e=b+2, the line in the file prior to preprocessing, that corresponds with line a+3 in the preprocessed file?

To do that, you need d=c-(a+1), the distance between the error line and the line that the last #line directive refers to, because that's how much to add to the actual error position vs. if the error had happened in the a+1 line. So we have:

d=c-(a+1)   (distance)
e=b+d (line number corresponding to `a+1` plus distance)

Now, the fact that both b and c are 1-based rather than 0-based, prompts the need for further corrections:

  1. The error is not reported by lslint at c, but at c+1 (one more than the zero-based line).
  2. The line in the #line directive is one more than the zero-based line corresponding to a+1.
  3. To report the correct line number we have to add 1 to e once we find it, because we've transformed everything to 0-based.

To compensate for (1), we have the real line coming from lslint, f=c+1. Solving for c we get that c=f-1. Replacing c in the distance formula we get: d=(f-1)-(a+1). Removing parentheses we get: d=f-a-2.

The line in the #line directive is not actually b. It's 1-based, while we assumed that b is 0-based. To account for that, which is issue (2) above, let's call the actual parameter to the #linedirective g, where g=b+1, and from that, b=g-1.

Now we can replace the variables in the original calculation, e=b+d, to take into account the actual inputs f and g. Replacing b=g-1 we get: e=(g-1)+d and replacing d=f-a-2 we get e=(g-1)+(f-a-2). Removing parentheses: e=g+f-a-3. We still need to report the 1-based line, h to account for (3), because e is 0-based, so I'll skip intermediate steps and add 1 to get the final result, which is: h=g+f-a-2.

To recap, the line to report, h, equals the line specified in the #line directive, g, plus the lslint error line, f, minus the zero-based line where #line is, a, minus 2.

You are grouping things a bit differently: you are calculating h=f-(a-g+2) which gives the exact same result after removing parentheses. That's your result = this_tuple.mcpp_in_line - this_tuple.orig_line + 2 when converting it to your naming. While it confused me a bit at the beginning, that has advantages. First, you can separate the calculation of (a-g+2) into its own function, that searches for the last appearance of c < a when given c=f-1 (the number - 1 in your call to getLastOffset). Second, if there is no #line directive before the given one, you return 0 instead, which means that in that case, h=f+0 (output reported line = input reported line) and the result is still correct.

That should work in every circumstance. There is no reason it shouldn't, unless mcpp has a bug, which I find hard to believe.

But calculating h'=f+abs(a-g+2) makes no sense at all, no matter how I look at it. That hack is going to bite you at some point for sure, because if there are remaining bugs, they are not in the math for sure.

And, while reviewing my post before submitting, I've realized that you break when this_tuple.mcpp_in_line >= inlined_line, i.e. you stop when a >= c aka when c <= a. That doesn't seem correct. You have to break when c >= a. The bug is most likely there, but you need to revert dc92a55.

Sei-Lisa commented 7 years ago

tl;dr version: revert dc92a55 and change the sense of the comparison in getLastOffset from <= to >=.

That, and reinstate number - 1 when calling getLastOffset. The - 1 was gone in 2af2961 for some reason.

Sei-Lisa commented 7 years ago

Scratch that. You must look for the last appearance of a < c (line with #line less than error line), so you must break when a >= c. Your break condition is right. If there is a bug, it must be elsewhere.

XenHat commented 7 years ago

@Sei-Lisa That was a lot of math but I think I got the gist of it. I had already figured the logic side of it, I guess I just instinctively avoided doing math where I could 😋

As for why abs() works: it gave me a correct but negative index when the file is very big. The index is right in small and big files but somehow in my production script it returns a negative version of it, so I just remove that with abs. I don't know why this happens, I just deal with it. The code:

if iter_line.startswith("TOTAL::") is False:
                    tokens = iter_line.split(',')
                    print('Tokens:[{0}]'.format(tokens))
                    token = tokens[0]
                    print("Token:{0}".format(token))
                    number = int(p.match(token).group(2).strip())
                    print("number: '{0}'".format(number))
                    offset = getLastOffset(preproc_bank, number)
                    print("Offset: {0}".format(offset))
                    tokminoff = str(number + int(offset))
                    print("Token + offset: {0}".format(tokminoff))
                    new_line = re.sub(str(number), tokminoff, iter_line)
                    print("New Line: {0}".format(new_line))
                    fixed_output_lines.append(new_line)
                    continue

Without the abs() call:

LINE:[ WARN:: (894, 16): variable `text' declared but never used.]
Tokens:[[' WARN:: (894', " 16): variable `text' declared but never used."]]
Token: WARN:: (894
number: '894'
Offset: -322
Token + offset: 572
New Line:  WARN:: (572, 16): variable `text' declared but never used.
LINE:[TOTAL:: Errors: 1  Warnings: 1]

With the abs() call:

LINE:[ WARN:: (894, 16): variable `text' declared but never used.]
Tokens:[[' WARN:: (894', " 16): variable `text' declared but never used."]]
Token: WARN:: (894
number: '894'
Offset: 322
Token + offset: 1216
New Line:  WARN:: (1216, 16): variable `text' declared but never used.
LINE:[TOTAL:: Errors: 1  Warnings: 1]
XenHat commented 7 years ago

I can't help with that. I have no idea what's the input file or any other debug info. The script you pasted gives no errors for me. I guess you're forcing some error somewhere, but no idea where or what the output should be and what it actually is.

https://github.com/XenHat/SublimeLinter-contrib-lslint/issues/6#issuecomment-336270734

Sei-Lisa commented 7 years ago

number: '894' Offset: -322 Token + offset: 572

You were not supposed to add it, you were supposed to subtract it. It's what it did in the beginning.

Token - offset = 894 - (-322) = 894 + 322 = 1216

It works.

Edit: "Offset" can be negative. When the line that contains #line is less than the parameter of #line, it will have a sign, and when it's greater, it will have the opposite sign. Nothing wrong with that. And with the abs, one of the cases will fail.

Sei-Lisa commented 7 years ago

Two cases where the offset has opposite signs:

case1.lsl

#if 0

#endif

default{timer(){x;}}

case2.lsl

#include "long.lsl"

default{timer(){x;}}

long.lsl:

list y = [
0,
1,
2,
3,
4,
5,
6,
7];

One of them will fail unless you revert dc92a55. Without the - 1 that was removed in 2af2961, it may fail when the error line is very close to a #line directive (one before or one after, not sure).

Edit: I used the same variable in case2.lsl as in long.lsl, so case2 won't have errors :( Edited to force an error.

XenHat commented 7 years ago

the -1 that was removed in 2af2961 was put back in the function, but somehow that change got lost somewhere. grrrrrrr.. 😠

Sei-Lisa commented 7 years ago

Yay! :+1:

What can be done about an error in a different file? Can it notify the main linter module, in order to automatically open the right file where the error is and report it? I really hope so.

If not, then I can only think of two alternatives. The ugliest is to just filter out the errors that correspond to a different file. The least bad is to try to guess where the #include was, and report the error in it. I have ideas for how to implement the latter, but they will complicate the code.

Edit: Sorry that I was so stubborn. :blush:

XenHat commented 7 years ago

RE:edit: No worries. I was too. 😊

About complexity: I'm not afraid of complexity with logic, but I'm pretty trash at math.

About the file thing... well, it would be easier if I could get the name of the file opened in the view, but no matter how I look at it, it seems impossible to get code that works fine in the editor's built-in console to behave properly in my linter plugin. I'm not sure why, either. Calls to file_name() from any of the two supported classes (windowcommand and textcommand just fail. I can't get anything "deeper" than getView then it just breaks. So I guess that's a nope.

However, we can probably treat "none" as "this file" and then do something with the lines coming from another file such as putting the marker at the position of the #include?

EDIT: if you would prefer to chat about this outside the bug tracker, you can hit me up in-world: https://my.secondlife.com/xenhat.liamano (or secondlife:///app/agent/f1a73716-4ad2-4548-9f0e-634c7a98fe86/im)

Sei-Lisa commented 7 years ago

Well, if anything, to not spam Winterwolf with technical details. But since I didn't find you online...

The question was not if you can access the filename. It's assumed that the main file is open in the editor, therefore you don't need to find its name in principle; you can assume that "<stdin>" means the main file and anything else means the file specified in the #line directive.

The question was if you can force the linter plugin to open a filename you give, in order to report errors in it. I presume that a C linter, for example, must be able to do exactly this, in order to report problems in the headers. Or any other language that supports includes, for the matter.

If it doesn't support it, maybe you can file a feature request asking to implement that.

But in case it's not supported, here's how I imagine the automatic detection of #include.

The basis of idea is that the preprocessor will insert a #line directive with a different filename at the exact point where it found the #include. Therefore, when an error is found in a different filename, your aim is to find the last #line directive which had "<stdin>" as a file before that line (call that L1), keeping track of where the first #line directive which changed the filename was (call that L2).

Then you replace the error line with L2, and do the same conversion math you're doing now using L1, and that's the line number that will appear in the final output.

Example:

top.lsl

   1 | string s; // just to add something
   2 | #include "level1.lsl"
   3 | default{state_entry(){llOwnerSay(s);}}

level1.lsl

   1 | #include "level2.lsl"

level2.lsl

   1 | integer x;

The goal is to report the unused identifier at line 2 of our file, which is the line with the include. The mcpp output is:

   1 | #line 1 "<stdin>"
   2 | string s;
   3 | #line 2 "<stdin>"
   4 | #line 1 "level1.lsl"
   5 | #line 1 "level2.lsl"
   6 | integer x;
   7 | #line 2 "level1.lsl"
   8 | #line 3 "<stdin>"
   9 | default{state_entry(){}}

The error lines reported by lslint are 2 and 6. For line 2, the last #line had "<stdin>" as file, therefore you do your usual thing.

For line 6, the last file was not "<stdin>", so you have to make a replacement. The last #line directive that had "<stdin>" is line 3, and the first #line directive after that one is line 4. Therefore, you replace the error line number as if it actually happened in line 4, because that's where the #include was (which is why the filename has changed). Then you do the usual thing, but using 4 as the error line number.

If all goes well, the output should be:

 WARN:: (  1,  8): variable `s' declared but never used.
 WARN:: (  2,  8): variable `t' declared but never used.
TOTAL:: Errors: 0  Warnings: 2
buildersbrewery commented 7 years ago

Reading through linter.py at f01e33f thinking out loud:

XenHat commented 7 years ago

1-3: Fixed 4: git is being a git 5: I like to prepare for the worst 6: read the docs, % is deprecated 7: I had to.

Sei-Lisa commented 7 years ago

Here's one (lazy) idea for solving the appending of info:

                    ...
                    # print("Offset: {0}".format(offset))
                    # tokminoff = str(number - int(offset))
                    tokminoff = str(number - int(offset))
                    # moved from below
                    # print("Token - offset: {0}".format(tokminoff))
                    new_line = re.sub(str(number), tokminoff, iter_line)
                    if result[1] != '"<stdin>"':
                        index = getLastStdin(preproc_bank, number)
                        # assert index != -1
                        new_number = preproc_bank[index + 1].mcpp_in_line + 1
                        offset = getLastOffset(preproc_bank, new_number)[0]
                        tokminoff = str(new_number - int(offset))
                        # the next line is best moved up to avoid calling p.match() twice
                        token_match = p.match(token)
                        new_line = '{0}:: ({1:>3},  1): in file {2}: {3}'.format(token_match.group(1), tokminoff, result[1], new_line)
                    # print("New Line: {0}".format(new_line))
                    fixed_output_lines.append(new_line)
                    continue
ghost commented 7 years ago

Sorry if I'm distracting, there is errors on linux again:

SublimeLinter: ERROR: could not launch '/usr/bin/mcpp -W0' 
SublimeLinter: reason: [Errno 2] No such file or directory: '/usr/bin/mcpp -W0' 
SublimeLinter: PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/winterwolf/Dropbox/bin:/snap/bin:/usr/lib/jvm/java-8-oracle/bin:/usr/lib/jvm/java-8-oracle/db/bin:/usr/lib/jvm/java-8-oracle/jre/bin:/snap/bin:/usr/lib/jvm/java-8-oracle/bin:/usr/lib/jvm/java-8-oracle/db/bin:/usr/lib/jvm/java-8-oracle/jre/bin 
SublimeLinter: ERROR: could not launch ['/home/winterwolf/Dropbox/bin/lslint', '-m', '-i', <property object at 0x7f61fcf2a8e8>] 
SublimeLinter: reason: Can't convert 'property' object to str implicitly 
SublimeLinter: PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/winterwolf/Dropbox/bin:/snap/bin:/usr/lib/jvm/java-8-oracle/bin:/usr/lib/jvm/java-8-oracle/db/bin:/usr/lib/jvm/java-8-oracle/jre/bin:/snap/bin:/usr/lib/jvm/java-8-oracle/bin:/usr/lib/jvm/java-8-oracle/db/bin:/usr/lib/jvm/java-8-oracle/jre/bin 
reloading settings Packages/User/lsl.sublime-settings
reloading settings Packages/User/ossl.sublime-settings
Package Control: Skipping automatic upgrade, last run at 2017-10-20 09:10:39, next run at 2017-10-20 10:10:39 or after

/usr/bin/mcpp exists! It is correct path, but not working :/

XenHat commented 7 years ago

Looks like Linux treats the executable path correctly and my hack doesn't work there. My OS broke and I had to reinstall it, so I lost the Linux VM.. this might take a few days :(

XenHat commented 7 years ago

Or not ;)

Sei-Lisa commented 7 years ago

So, if everything goes right, the output of the top.lsl example should look like this:

 WARN:: (  1,  8): variable `s' declared but never used.
WARN:: (  2,  1): in file "level2.lsl": WARN:: (  1,  8): variable `t' declared but never used.
TOTAL:: Errors: 0  Warnings: 2

(The lack of a space at the beginning of the second line is because the regex doesn't capture leading space, but that's only cosmetic.)

This would create two warnings, one at line 1 and the other at line 2 of the main file (top.lsl). The first warning would look just as usual. The second warning would point to column 1 of the #include line that included the file, even if indirectly, because the warning is inside it. The text of the warning would be:

in file "level2.lsl": WARN:: (  1,  8): variable `t' declared but never used.

which allows the user to go to level2.lsl and check line 1 column 8 manually.

Lacking any support for file arguments in SublimeLinter, I think this is the best that can be done and we can declare this issue as fixed.

XenHat commented 7 years ago

@Sei-Lisa I'm only getting one warning.. :(

SublimeLinter: lslint output:
WARN:: (  1,  1): in file "level2.lsl":  WARN:: (  1,  9): variable `x' declared but never used.
TOTAL:: Errors: 0  Warnings: 1 

EDIT: Figured something

Sei-Lisa commented 7 years ago

My bad, apologies. I changed my top.lsl like this, and forgot to update the message:

   1 | string s; // just to add something
   2 | #include "level1.lsl"
   3 | default{state_entry(){}}

Before that change, there was nothing wrong with line 1, so no warning was emitted for it.

XenHat commented 7 years ago

Nah, it was something else ^^ my top already looks like this, cleaning up and commiting

XenHat commented 7 years ago

Forgot to tag https://github.com/XenHat/SublimeLinter-contrib-lslint/commit/9802e109101b70e4dd0c83d67aebb27365b201f2

XenHat commented 7 years ago

Implemented the best we could given SublimeLinter's limitations.