Separate diagnostics from rule results (#1423)

This commit is contained in:
Moritz Kiefer 2019-05-28 14:18:59 +02:00 committed by GitHub
parent 34d8d705c7
commit 330ede08b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 152 additions and 404 deletions

View File

@ -444,9 +444,9 @@ load("@bazel_skylib//lib:dicts.bzl", "dicts")
# For the time being we build with GMP. See https://github.com/digital-asset/daml/issues/106
use_integer_simple = not is_windows
HASKELL_LSP_COMMIT = "6e34a2193464dd49b09e223111c57a39c44fb1c7"
HASKELL_LSP_COMMIT = "4dfbe392ab235048bb42991a5e259ff5f317244f"
HASKELL_LSP_HASH = "5804143e94ede0f99962007f94e7f84268f220c05ac3aeae3dda3cdc186d077f"
HASKELL_LSP_HASH = "164311a83a7fc8a733c71354b87e3e6425afbbbba033a64f38e88b81c32c1fbd"
hazel_repositories(
core_packages = dicts.add(
@ -508,13 +508,16 @@ hazel_repositories(
hazel_hackage("terminal-progress-bar", "0.4.0.1", "c5a9720fcbcd9d83f9551e431ee3975c61d7da6432aa687aef0c0e04e59ae277") +
hazel_hackage("rope-utf16-splay", "0.3.1.0", "cbf878098355441ed7be445466fcb72d45390073a298b37649d762de2a7f8cc6") +
hazel_hackage("unix-compat", "0.5.1", "a39d0c79dd906763770b80ba5b6c5cb710e954f894350e9917de0d73f3a19c52") +
# This is a special version of Haskell LSP without GPL dependencies
hazel_github(
# This is a version of haskell-lsp that has not yet been released and contains
# a few fixes for the uri <-> filepath conversion.
hazel_github_external(
"alanz",
"haskell-lsp",
HASKELL_LSP_COMMIT,
HASKELL_LSP_HASH,
) +
hazel_github(
hazel_github_external(
"alanz",
"haskell-lsp",
HASKELL_LSP_COMMIT,
HASKELL_LSP_HASH,

View File

@ -21,6 +21,7 @@ depends = [
"mtl",
"pretty",
"safe-exceptions",
"sorted-list",
"shake",
"stm",
"syb",

View File

@ -42,10 +42,6 @@ newtype GlobalDirtyFiles = GlobalDirtyFiles (Var DirtyFiles)
instance IsIdeGlobal GlobalDirtyFiles
-- | Get the modification time of a file.
type instance RuleResult GetModificationTime = UTCTime
-- | Get the contents of a file, either dirty (if the buffer is modified) or from disk.
type instance RuleResult GetFileContents = (UTCTime, StringBuffer)
@ -58,11 +54,6 @@ data GetFileExists = GetFileExists
instance Hashable GetFileExists
instance NFData GetFileExists
data GetModificationTime = GetModificationTime
deriving (Eq, Show, Generic)
instance Hashable GetModificationTime
instance NFData GetModificationTime
data GetFileContents = GetFileContents
deriving (Eq, Show, Generic)
instance Hashable GetFileContents

View File

@ -24,7 +24,7 @@
-- useStale.
module Development.IDE.State.Shake(
IdeState,
IdeRule, IdeResult,
IdeRule, IdeResult, GetModificationTime(..),
shakeOpen, shakeShut,
shakeRun,
shakeProfile,
@ -55,19 +55,18 @@ import Data.List.Extra
import qualified Data.Text as T
import Development.IDE.Logger as Logger
import Development.IDE.Types.LSP
import Development.IDE.Types.Diagnostics
import Development.IDE.Types.Diagnostics hiding (getAllDiagnostics)
import qualified Development.IDE.Types.Diagnostics as D
import Control.Concurrent.Extra
import Control.Exception
import Control.DeepSeq
import System.Time.Extra
import Data.Typeable
import Data.Tuple.Extra
import System.Directory
import System.FilePath
import System.FilePath hiding (makeRelative)
import qualified Development.Shake as Shake
import Control.Monad.Extra
import qualified Data.Set as Set
import Data.Time
import GHC.Generics
import System.IO.Unsafe
import Numeric.Extra
@ -79,6 +78,7 @@ data ShakeExtras = ShakeExtras
,logger :: Logger.Handle
,globals :: Var (Map.HashMap TypeRep Dynamic)
,state :: Var Values
,diagnostics :: Var (ProjectDiagnostics Key)
}
getShakeExtras :: Action ShakeExtras
@ -116,12 +116,7 @@ getIdeGlobalState = getIdeGlobalExtras . shakeExtras
-- | The state of the all values - nested so you can easily find all errors at a given file.
type Values =
Map.HashMap FilePath
(Map.HashMap Key
(IdeResult Dynamic)
)
type Values = Map.HashMap (FilePath, Key) (Maybe Dynamic)
-- | Key type
data Key = forall k . (Typeable k, Hashable k, Eq k, Show k) => Key k
@ -198,13 +193,10 @@ setValues :: IdeRule k v
=> Var Values
-> k
-> FilePath
-> IdeResult v
-> IO (Maybe [FileDiagnostic], [FileDiagnostic]) -- ^ (before, after)
setValues state key file val = modifyVar state $ \inVal -> do
let k = Key key
outVal = Map.insertWith Map.union file (Map.singleton k $ second (fmap toDyn) val) inVal
f = concatMap fst . Map.elems
return (outVal, (f <$> Map.lookup file inVal, f $ outVal Map.! file))
-> Maybe v
-> IO ()
setValues state key file val = modifyVar_ state $
pure . Map.insert (file, Key key) (fmap toDyn val)
-- | The outer Maybe is Nothing if this function hasn't been computed before
-- the inner Maybe is Nothing if the result of the previous computation failed to produce
@ -213,9 +205,8 @@ getValues :: forall k v. IdeRule k v => Var Values -> k -> FilePath -> IO (Maybe
getValues state key file = do
vs <- readVar state
return $ do
f <- Map.lookup file vs
v <- Map.lookup (Key key) f
pure $ fmap (fromJust . fromDynamic @v) $ snd v
v <- Map.lookup (file, Key key) vs
pure $ fmap (fromJust . fromDynamic @v) v
-- | Open a 'IdeState', should be shut using 'shakeShut'.
shakeOpen :: (Event -> IO ()) -- ^ diagnostic handler
@ -223,8 +214,12 @@ shakeOpen :: (Event -> IO ()) -- ^ diagnostic handler
-> ShakeOptions
-> Rules ()
-> IO IdeState
shakeOpen diags shakeLogger opts rules = do
shakeExtras <- ShakeExtras diags shakeLogger <$> newVar Map.empty <*> newVar Map.empty
shakeOpen eventer logger opts rules = do
shakeExtras <- do
globals <- newVar Map.empty
state <- newVar Map.empty
diagnostics <- newVar emptyDiagnostics
pure ShakeExtras{..}
(shakeDb, shakeClose) <- shakeOpenDatabase opts{shakeExtra = addShakeExtra shakeExtras $ shakeExtra opts} rules
shakeAbort <- newVar $ return ()
shakeDb <- shakeDb
@ -263,20 +258,22 @@ useStale IdeState{shakeExtras=ShakeExtras{state}} k fp =
getAllDiagnostics :: IdeState -> IO [FileDiagnostic]
getAllDiagnostics IdeState{shakeExtras = ShakeExtras{state}} = do
val <- readVar state
return $ concatMap (concatMap fst . Map.elems) $ Map.elems val
getAllDiagnostics IdeState{shakeExtras = ShakeExtras{diagnostics}} = do
val <- readVar diagnostics
return $ D.getAllDiagnostics val
-- | FIXME: This function is temporary! Only required because the files of interest doesn't work
unsafeClearAllDiagnostics :: IdeState -> IO ()
unsafeClearAllDiagnostics IdeState{shakeExtras = ShakeExtras{state}} = modifyVar_ state $
return . Map.map (Map.map (\(_, x) -> ([], x)))
unsafeClearAllDiagnostics IdeState{shakeExtras = ShakeExtras{diagnostics}} =
writeVar diagnostics emptyDiagnostics
-- | Clear the results for all files that do not match the given predicate.
garbageCollect :: (FilePath -> Bool) -> Action ()
garbageCollect keep = do
ShakeExtras{state} <- getShakeExtras
liftIO $ modifyVar_ state $ return . Map.filterWithKey (\file _ -> keep file)
ShakeExtras{state, diagnostics} <- getShakeExtras
liftIO $
do modifyVar_ state $ return . Map.filterWithKey (\(file, _) _ -> keep file)
modifyVar_ diagnostics $ return . filterDiagnostics keep
define
:: IdeRule k v
@ -354,7 +351,7 @@ defineEarlyCutoff
=> (k -> FilePath -> Action (Maybe BS.ByteString, IdeResult v))
-> Rules ()
defineEarlyCutoff op = addBuiltinRule noLint noIdentity $ \(Q (key, file)) old mode -> do
ShakeExtras{state} <- getShakeExtras
extras@ShakeExtras{state} <- getShakeExtras
val <- case old of
Just old | mode == RunDependenciesSame -> do
v <- liftIO $ getValues state key file
@ -365,46 +362,39 @@ defineEarlyCutoff op = addBuiltinRule noLint noIdentity $ \(Q (key, file)) old m
case val of
Just res -> return res
Nothing -> do
(bs, res) <- actionCatch
(bs, (diags, res)) <- actionCatch
(do v <- op key file; liftIO $ evaluate $ force v) $
\(e :: SomeException) -> pure (Nothing, ([ideErrorText file $ T.pack $ show e | not $ isBadDependency e],Nothing))
res <- return $ first (map $ \(_,d) -> (file,d)) res
(before, after) <- liftIO $ setValues state key file res
updateFileDiagnostics file before after
liftIO $ setValues state key file res
updateFileDiagnostics file (Key key) extras $ map snd diags
let eq = case (bs, fmap unwrap old) of
(Just a, Just (Just b)) -> a == b
_ -> False
return $ RunResult
(if eq then ChangedRecomputeSame else ChangedRecomputeDiff)
(wrap bs)
$ A (snd res) bs
$ A res bs
where
wrap = maybe BS.empty (BS.cons '_')
unwrap x = if BS.null x then Nothing else Just $ BS.tail x
updateFileDiagnostics ::
FilePath
-> Maybe [FileDiagnostic] -- ^ previous results for this file
-> [FileDiagnostic] -- ^ current results
-> Key
-> ShakeExtras
-> [Diagnostic] -- ^ current results
-> Action ()
updateFileDiagnostics afp previousAll currentAll = do
-- TODO (MK) We canonicalize to make sure that the two files agree on use of
-- / and \ and other shenanigans.
-- Once we have finished the migration to haskell-lsp we should make sure that
-- this is no longer necessary.
afp' <- liftIO $ canonicalizePath afp
let filtM diags = do
diags' <-
filterM
(\x -> fmap (== afp') (canonicalizePath $ fst x))
diags
pure (Set.fromList diags')
previous <- liftIO $ traverse filtM previousAll
current <- liftIO $ filtM currentAll
when (Just current /= previous) $
sendEvent $ EventFileDiagnostics $ (afp, map snd $ Set.toList current)
updateFileDiagnostics fp k ShakeExtras{diagnostics, state} current = do
(newDiags, oldDiags) <- liftIO $ do
modTime <- join <$> getValues state GetModificationTime fp
modifyVar diagnostics $ \old -> do
let oldDiags = getFileDiagnostics fp old
let newDiagsStore = setStageDiagnostics fp modTime k current old
let newDiags = getFileDiagnostics fp newDiagsStore
pure (newDiagsStore, (newDiags, oldDiags))
when (newDiags /= oldDiags) $
sendEvent $ EventFileDiagnostics (fp, newDiags)
setPriority :: (Enum a) => a -> Action ()
@ -424,3 +414,11 @@ logDebug, logSeriousError
:: IdeState -> T.Text -> IO ()
logDebug = sl Logger.logDebug
logSeriousError = sl Logger.logSeriousError
data GetModificationTime = GetModificationTime
deriving (Eq, Show, Generic)
instance Hashable GetModificationTime
instance NFData GetModificationTime
-- | Get the modification time of a file.
type instance RuleResult GetModificationTime = UTCTime

View File

@ -27,12 +27,16 @@ module Development.IDE.Types.Diagnostics (
ideTryIOException,
showDiagnostics,
showDiagnosticsColored,
prettyDiagnosticStore,
defDiagnostic,
addDiagnostics,
filterSeriousErrors,
filePathToUri,
getDiagnosticsFromStore
uriToFilePath',
ProjectDiagnostics,
emptyDiagnostics,
setStageDiagnostics,
getAllDiagnostics,
filterDiagnostics,
getFileDiagnostics,
prettyDiagnostics
) where
import Control.Exception
@ -40,14 +44,17 @@ import Data.Either.Combinators
import Data.Maybe as Maybe
import Data.Foldable
import qualified Data.Map as Map
import Data.Time.Clock
import Data.Time.Clock.POSIX
import qualified Data.Text as T
import Data.Text.Prettyprint.Doc.Syntax
import qualified Data.SortedList as SL
import qualified Text.PrettyPrint.Annotated.HughesPJClass as Pretty
import Language.Haskell.LSP.Types as LSP (
import qualified Language.Haskell.LSP.Types as LSP
import Language.Haskell.LSP.Types as LSP (
DiagnosticSeverity(..)
, Diagnostic(..)
, filePathToUri
, uriToFilePath
, List(..)
, DiagnosticRelatedInformation(..)
, Uri(..)
@ -56,6 +63,15 @@ import Language.Haskell.LSP.Diagnostics
import Development.IDE.Types.Location
-- | We use an empty string as a filepath when we dont have a file.
-- However, haskell-lsp doesnt support that in uriToFilePath and given
-- that it is not a valid filepath it does not make sense to upstream a fix.
-- So we have our own wrapper here that supports empty filepaths.
uriToFilePath' :: Uri -> Maybe FilePath
uriToFilePath' uri
| uri == filePathToUri "" = Just ""
| otherwise = LSP.uriToFilePath uri
ideErrorText :: FilePath -> T.Text -> FileDiagnostic
ideErrorText fp = errorDiag fp "Ide Error"
@ -96,28 +112,6 @@ defDiagnostic _range _message = LSP.Diagnostic {
, _relatedInformation = Nothing
}
filterSeriousErrors ::
FilePath ->
[LSP.Diagnostic] ->
[LSP.Diagnostic]
filterSeriousErrors fp =
filter (maybe False hasSeriousErrors . LSP._relatedInformation)
where
hasSeriousErrors :: List DiagnosticRelatedInformation -> Bool
hasSeriousErrors (List a) = any ((/=) uri . _uri . _location) a
uri = LSP.filePathToUri fp
addDiagnostics ::
FilePath ->
[LSP.Diagnostic] ->
DiagnosticStore -> DiagnosticStore
addDiagnostics fp diags ds =
updateDiagnostics
ds
(LSP.filePathToUri fp)
Nothing $
partitionBySource diags
ideTryIOException :: FilePath -> IO a -> IO (Either FileDiagnostic a)
ideTryIOException fp act =
mapLeft (\(e :: IOException) -> ideErrorText fp $ T.pack $ show e) <$> try act
@ -167,20 +161,61 @@ prettyDiagnostic (fp, LSP.Diagnostic{..}) =
where
sev = fromMaybe LSP.DsError _severity
prettyDiagnosticStore :: DiagnosticStore -> Doc SyntaxClass
prettyDiagnosticStore ds =
vcat $
map (\(uri, diags) -> prettyFileDiagnostics (fromMaybe noFilePath $ uriToFilePath uri, diags)) $
Map.assocs $
Map.map getDiagnosticsFromStore ds
prettyFileDiagnostics :: FileDiagnostics -> Doc SyntaxClass
prettyFileDiagnostics (filePath, diags) =
slabel_ "Compiler error in" $ vcat
[ slabel_ "File:" $ pretty filePath
, slabel_ "Errors:" $ vcat $ map (prettyDiagnostic . (filePath,)) diags
]
getDiagnosticsFromStore :: StoreItem -> [Diagnostic]
getDiagnosticsFromStore (StoreItem _ diags) =
toList =<< Map.elems diags
-- | This represents every diagnostic in a LSP project, the stage type variable is
-- the type of the compiler stages, in this project that is always the Key data
-- type found in Development.IDE.State.Shake
newtype ProjectDiagnostics stage = ProjectDiagnostics {getStore :: DiagnosticStore}
deriving Show
emptyDiagnostics :: ProjectDiagnostics stage
emptyDiagnostics = ProjectDiagnostics mempty
-- | Sets the diagnostics for a file and compilation step
-- if you want to clear the diagnostics call this with an empty list
setStageDiagnostics ::
Show stage =>
FilePath ->
Maybe UTCTime ->
-- ^ the time that the file these diagnostics originate from was last edited
stage ->
[LSP.Diagnostic] ->
ProjectDiagnostics stage ->
ProjectDiagnostics stage
setStageDiagnostics fp timeM stage diags (ProjectDiagnostics ds) =
ProjectDiagnostics $ updateDiagnostics ds uri posixTime diagsBySource
where
diagsBySource = Map.singleton (Just $ T.pack $ show stage) (SL.toSortedList diags)
posixTime :: Maybe Int
posixTime = fmap (fromEnum . utcTimeToPOSIXSeconds) timeM
uri = filePathToUri fp
fromUri :: LSP.Uri -> FilePath
fromUri = fromMaybe noFilePath . uriToFilePath'
getAllDiagnostics ::
ProjectDiagnostics stage ->
[FileDiagnostic]
getAllDiagnostics =
concatMap (\(k,v) -> map (fromUri k,) $ getDiagnosticsFromStore v) . Map.toList . getStore
getFileDiagnostics ::
FilePath ->
ProjectDiagnostics stage ->
[LSP.Diagnostic]
getFileDiagnostics fp ds =
maybe [] getDiagnosticsFromStore $
Map.lookup (filePathToUri fp) $
getStore ds
filterDiagnostics ::
(FilePath -> Bool) ->
ProjectDiagnostics stage ->
ProjectDiagnostics stage
filterDiagnostics keep =
ProjectDiagnostics .
Map.filterWithKey (\uri _ -> maybe True keep $ uriToFilePath' uri) .
getStore

View File

@ -44,7 +44,7 @@ import Development.IDE.State.Rules.Daml
import qualified Development.IDE.Logger as Logger
import Development.IDE.Types.LSP
import DA.Daml.GHC.Compiler.Options (defaultOptionsIO)
import Language.Haskell.LSP.Types (uriToFilePath, Range)
import Language.Haskell.LSP.Types (Range)
-- * external dependencies
import Control.Concurrent.STM
@ -263,7 +263,7 @@ cursorPosition (_absPath, line, col) = D.Position line col
locationStartCursor :: D.Location -> Cursor
locationStartCursor (D.Location path (D.Range (D.Position line col) _)) =
(fromMaybe D.noFilePath $ uriToFilePath path, line, col)
(fromMaybe D.noFilePath $ D.uriToFilePath' path, line, col)
-- | Same as Cursor, but passing a list of columns, so you can specify a range
-- such as (foo,1,[10..20]).
@ -376,7 +376,7 @@ matchGoToDefinitionPattern = \case
In m -> \l -> fromMaybe False $ do
l' <- l
let uri = D._uri l'
fp <- uriToFilePath uri
fp <- D.uriToFilePath' uri
pure $ isSuffixOf (moduleNameToFilePath m) fp
-- | Expect "go to definition" to point us at a certain location or to fail.

View File

@ -207,7 +207,7 @@ checkDiagnostics log expected got = do
(\expFields -> not $ any (\diag -> all (checkField diag) expFields) got)
expected
pure $ if
| length expected /= length got -> Just $ "Wrong number of diagnostics, expected " ++ show (length expected)
| length expected /= length got -> Just $ "Wrong number of diagnostics, expected " ++ show (length expected) ++ ", but got " ++ show (length got)
| null bad -> Nothing
| otherwise -> Just $ unlines ("Could not find matching diagnostics:" : map show bad)
where checkField :: D.FileDiagnostic -> DiagnosticField -> Bool

View File

@ -1,182 +0,0 @@
// Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
import * as DT from '../daml-test';
import * as fs from 'fs';
import * as assert from 'assert';
import * as path from 'path';
import * as Rx from 'rxjs'
describe("issue reports", function() {
// DEL-6241: DAML-GHC not unloading modules from
// scenario service, leading to internal error
// when hashes are missing for definitions.
//
// The test opens two modules A and B, where
// A depends on definition in B. A has a failing scenario.
// The module A is then closed and we expect the
// scenario diagnostics to clear. Finally we remove
// the definition from B that A depends on and add
// a failing scenario to A.
//
// Since currently scenario diagnostics are not properly reported
// this test only validates that the "Ide Error" diagnostic is gone
// that was shown when the scenario service context update fails.
DT.testDaml("DEL-6241", connection => done => {
const uriA = DT.utils.toRequestUri("A.daml");
const aContents0 = `
daml 1.2 module A where
x : Int
x = 123
`;
const aContents1 = `
daml 1.2 module A where
-- x is gone
`;
const uriB = DT.utils.toRequestUri("B.daml");
const bContents = `
daml 1.2 module B where
import A
testScenario = scenario do
pure x
`;
enum steps {
step1_DiagnosticsForB,
step2_ClosedB
};
var currentStep = steps.step1_DiagnosticsForB;
var step2timeout = null;
var step2_seenA = false;
const step = (diagnostic) => {
switch(currentStep) {
case steps.step1_DiagnosticsForB: {
// step 1: We wait for diagnostics for B before we close it.
if (diagnostic.uri.indexOf("B.daml") >= 0) {
step2timeout = setTimeout(done, 10000);
currentStep = steps.step2_ClosedB;
connection.closeDocument(uriB);
connection.changeDocument(
uriA, 1, aContents1);
}
break;
}
case steps.step2_ClosedB: {
// step 2: We check that no errors arrive for A
// before 'step2timeout' fires.
if (diagnostic.uri.indexOf("A.daml") >= 0) {
const eq = DT.utils.deepEqual(
diagnostic.diagnostics.map(d => d.message),
[]);
if(!eq.equal) {
clearTimeout(step2timeout);
done(eq.message);
}
}
break;
}
}
};
connection
.diagnostics
.subscribe(
{ next: step,
error: (err) => done(err)
});
connection.openDocument(uriA, aContents0);
connection.openDocument(uriB, bContents);
})
// NOTE(JM): Disabled due to DEL-5741. Re-enable once fixed.
/*
// see https://digitalasset.atlassian.net/browse/PROD-3898
// Test works by loading a file with an import that hasn't been fully
// typed (as in written) yet.
// It then simulates typing the import by changing the file one
// character at a time.
// At the end we don't want any diagnostics left for the file.
DT.testDaml("PROD-3898", (connection) => (done) => {
const theImport = "tests/issue-reports/PROD-3898/TheImport.daml";
const main0 = "tests/issue-reports/PROD-3898/Main.daml";
const main1 = "tests/issue-reports/PROD-3898/Main1.daml";
const main2 = "tests/issue-reports/PROD-3898/Main2.daml";
const text0 = fs.readFileSync(main0, 'UTF-8');
const text1 = fs.readFileSync(main1, 'UTF-8');
const text2 = fs.readFileSync(main2, 'UTF-8');
const file0 = DT.utils.toRequestUri(main0);
const theImportText = fs.readFileSync(theImport, 'UTF-8');
const theImportFile = DT.utils.toRequestUri(theImport);
const mainDiagnostics = connection.diagnostics
.filter((diagnostic) => diagnostic.uri.indexOf("Main.daml") >= 0)
.map((diagnostic) => diagnostic.diagnostics.map((d) => d.message));
enum steps { step1, step2, step3 }
let currentStep = steps.step1;
let expectedDiagnostic1 =
[ 'Module could not be found: TheImpo'
];
let expectedDiagnostic2 =
[ 'Module could not be found: TheImpor'
];
mainDiagnostics.subscribe(
{
next: (diagnostic) => {
switch(currentStep) {
case steps.step1: {
const eq = DT.utils.deepEqual(diagnostic, expectedDiagnostic1);
if(eq.equal) {
connection.changeDocument(file0, 1, text1);
currentStep = steps.step2;
}
else {
done(eq.message);
}
break
}
case steps.step2: {
const eq = DT.utils.deepEqual(diagnostic, expectedDiagnostic2);
if(eq.equal) {
connection.changeDocument(file0, 2, text2);
currentStep = steps.step3;
}
else {
done(eq.message);
}
break
}
case steps.step3: {
const eq = DT.utils.deepEqual(diagnostic, []);
if(eq.equal) {
done();
}
else {
done(eq.message);
}
break;
}
}
},
error: (err) => done(err)
}
);
connection.openDocument(theImportFile, theImportText);
connection.openDocument(file0, text0);
});
*/
});

View File

@ -30,9 +30,5 @@
"source": "Compiler",
"message": "/tests/diagnostics/failed-name-resolution/Main.daml:11:10: error:\n • Variable not in scope: abdd : Int -> Int -> Int\n • Perhaps you meant add (line 8)"
}
],
"file:/tests/diagnostics/failed-name-resolution/Prelude.daml": [],
"file:/tests/diagnostics/failed-name-resolution/DA/Internal/Record.daml": [],
"file:/tests/diagnostics/failed-name-resolution/DA/Internal/Desugar.daml": [],
"file:/tests/diagnostics/failed-name-resolution/DA/Internal/RebindableSyntax.daml": []
]
}

View File

@ -16,10 +16,6 @@
"message": "Cyclic module dependency between A, B, Main"
}
],
"file:/tests/diagnostics/import-cycle/Prelude.daml": [],
"file:/tests/diagnostics/import-cycle/DA/Internal/Desugar.daml": [],
"file:/tests/diagnostics/import-cycle/DA/Internal/Record.daml": [],
"file:/tests/diagnostics/import-cycle/DA/Internal/RebindableSyntax.daml": [],
"file:/tests/diagnostics/import-cycle/A.daml": [
{
"severity": 1,
@ -54,4 +50,4 @@
"message": "Cyclic module dependency between A, B, Main"
}
]
}
}

View File

@ -15,10 +15,5 @@
"source": "Compiler",
"message": "/tests/diagnostics/import-error/Main.daml:7:8: error:\n Could not find module Oops\nIt is not a module in the current program, or in any known package."
}
],
"file:/tests/diagnostics/import-error/Prelude.daml": [],
"file:/tests/diagnostics/import-error/DA/Internal/Desugar.daml": [],
"file:/tests/diagnostics/import-error/DA/Internal/Record.daml": [],
"file:/tests/diagnostics/import-error/DA/Internal/RebindableSyntax.daml": [],
"file:/tests/diagnostics/import-error/Oops.daml": []
]
}

View File

@ -1,7 +0,0 @@
{
"file:/tests/diagnostics/library-modules/Main.daml": [],
"file:/tests/diagnostics/library-modules/Prelude.daml": [],
"file:/tests/diagnostics/library-modules/DA/Internal/Desugar.daml": [],
"file:/tests/diagnostics/library-modules/DA/Internal/Record.daml": [],
"file:/tests/diagnostics/library-modules/DA/Internal/RebindableSyntax.daml": []
}

View File

@ -1,9 +0,0 @@
-- Copyright (c) 2019, Digital Asset (Switzerland) GmbH and/or its affiliates.
-- All rights reserved.
daml 1.2
module Extra where
x = 1
oops =

View File

@ -1,8 +0,0 @@
-- Copyright (c) 2019, Digital Asset (Switzerland) GmbH and/or its affiliates.
-- All rights reserved.
daml 1.2
module LibraryModules where
import Main
import Extra

View File

@ -1,7 +0,0 @@
-- Copyright (c) 2019, Digital Asset (Switzerland) GmbH and/or its affiliates.
-- All rights reserved.
daml 1.2
module Main where
test_main = 10

View File

@ -1,9 +1,4 @@
{
"file:/tests/diagnostics/multi-module-funny/Main.daml": [],
"file:/tests/diagnostics/multi-module-funny/Prelude.daml": [],
"file:/tests/diagnostics/multi-module-funny/DA/Internal/Desugar.daml": [],
"file:/tests/diagnostics/multi-module-funny/DA/Internal/Record.daml": [],
"file:/tests/diagnostics/multi-module-funny/DA/Internal/RebindableSyntax.daml": [],
"file:/tests/diagnostics/multi-module-funny/Libs/A.daml": [
{
"severity": 1,
@ -37,10 +32,5 @@
"source": "Typechecker",
"message": "/tests/diagnostics/multi-module-funny/Libs/B.daml:7:1: warning:\n The import of Libs.C is redundant\n except perhaps to import instances from Libs.C\n To import instances alone, use: import Libs.C()"
}
],
"file:/tests/diagnostics/multi-module-funny/Libs/Prelude.daml": [],
"file:/tests/diagnostics/multi-module-funny/Libs/DA/Internal/Desugar.daml": [],
"file:/tests/diagnostics/multi-module-funny/Libs/DA/Internal/Record.daml": [],
"file:/tests/diagnostics/multi-module-funny/Libs/DA/Internal/RebindableSyntax.daml": [],
"file:/tests/diagnostics/multi-module-funny/Libs/C.daml": []
}
]
}

View File

@ -1,9 +0,0 @@
{
"file:/tests/diagnostics/multi-module/Main.daml": [],
"file:/tests/diagnostics/multi-module/Prelude.daml": [],
"file:/tests/diagnostics/multi-module/DA/Internal/Desugar.daml": [],
"file:/tests/diagnostics/multi-module/DA/Internal/Record.daml": [],
"file:/tests/diagnostics/multi-module/DA/Internal/RebindableSyntax.daml": [],
"file:/tests/diagnostics/multi-module/Libs/A.daml": [],
"file:/tests/diagnostics/multi-module/Libs/B.daml": []
}

View File

@ -1,10 +0,0 @@
-- Copyright (c) 2019, Digital Asset (Switzerland) GmbH and/or its affiliates.
-- All rights reserved.
daml 1.2
module Libs.A where
import Libs.B
double : Int -> Int
double x = idInt x * idInt x

View File

@ -1,8 +0,0 @@
-- Copyright (c) 2019, Digital Asset (Switzerland) GmbH and/or its affiliates.
-- All rights reserved.
daml 1.2
module Libs.B where
idInt : Int -> Int
idInt x = x

View File

@ -1,10 +0,0 @@
-- Copyright (c) 2019, Digital Asset (Switzerland) GmbH and/or its affiliates.
-- All rights reserved.
daml 1.2
module Main where
import Libs.A
test_main : Int
test_main = double 10

View File

@ -15,9 +15,5 @@
"source": "Scenario",
"message": "Scenario execution failed on commit at Main:28:5:\n #0: create of Main:Agree at DA.Internal.Prelude:356:1\n failed due to a missing authorization from 'Alice'\n\nLast source location: DA.Internal.Prelude:356:1\n\nLedger time: 1970-01-01T00:00:00Z\n\nPartial transaction:\n Sub-transactions:\n #0\n └─> create Main:Agree\n with\n p1 = 'Foo'; p2 = 'Alice'"
}
],
"file:/tests/diagnostics/scenario-error/Prelude.daml": [],
"file:/tests/diagnostics/scenario-error/DA/Internal/Record.daml": [],
"file:/tests/diagnostics/scenario-error/DA/Internal/Desugar.daml": [],
"file:/tests/diagnostics/scenario-error/DA/Internal/RebindableSyntax.daml": []
]
}

View File

@ -15,9 +15,5 @@
"source": "Compiler",
"message": "/tests/diagnostics/type-error/Main.daml:7:12: error:\n • Couldn't match expected type Int with actual type Text\n • In the second argument of (+), namely \"foo\"\n In the expression: 1 + \"foo\"\n In an equation for oops: oops = 1 + \"foo\""
}
],
"file:/tests/diagnostics/type-error/Prelude.daml": [],
"file:/tests/diagnostics/type-error/DA/Internal/Desugar.daml": [],
"file:/tests/diagnostics/type-error/DA/Internal/Record.daml": [],
"file:/tests/diagnostics/type-error/DA/Internal/RebindableSyntax.daml": []
]
}

View File

@ -8,6 +8,7 @@ This page contains release notes for the SDK.
HEAD — ongoing
--------------
- Fixed a bug where type check errors would persist if there was a subsequent parse error
0.12.21 - 2019-05-28
--------------------